Merge pull request #3 from AuthMe-Team/master

Update my fork
This commit is contained in:
FabioZumbi12 2016-03-05 15:26:57 -03:00
commit b9b5cba94e
55 changed files with 1447 additions and 934 deletions

View File

@ -58,7 +58,7 @@ McStats: http://mcstats.org/plugin/AuthMe
#####"The best authentication plugin for the Bukkit/Spigot API!" #####"The best authentication plugin for the Bukkit/Spigot API!"
<p>Prevent username stealing on your server! Fully compatible with UUIDs and Craftbukkit/Spigot 1.8.X!<br> <p>Prevent username stealing on your server!<br>
Use it to secure your Offline mode server or to increase your Online mode server's protection!</p> Use it to secure your Offline mode server or to increase your Online mode server's protection!</p>
<p>AuthMeReloaded disallows players who aren't authenticated to do actions like placing blocks, moving,<br> <p>AuthMeReloaded disallows players who aren't authenticated to do actions like placing blocks, moving,<br>

157
pom.xml
View File

@ -48,22 +48,25 @@
</prerequisites> </prerequisites>
<properties> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- Project Properties --> <!-- Project Properties -->
<projectEncoding>UTF-8</projectEncoding>
<project.build.sourceEncoding>${projectEncoding}</project.build.sourceEncoding>
<project.build.outputEncoding>${projectEncoding}</project.build.outputEncoding>
<jdkVersion>1.7</jdkVersion>
<testJreVersion>1.7</testJreVersion>
<!-- Output properties -->
<pluginName>AuthMe</pluginName> <pluginName>AuthMe</pluginName>
<jarName>${pluginName}-${project.version}</jarName> <jarName>${pluginName}-${project.version}</jarName>
<mainClass>fr.xephi.authme.AuthMe</mainClass> <mainClass>${project.groupId}.${project.artifactId}.${pluginName}</mainClass>
<pluginAuthors>Xephi, sgdc3, DNx5, timvisee, games647, ljacqu</pluginAuthors> <pluginAuthors>Xephi, sgdc3, DNx5, timvisee, games647, ljacqu</pluginAuthors>
<buildNumber>Unknown</buildNumber> <buildNumber>Unknown</buildNumber>
<!-- Change Compiler Version (JDK) HERE! -->
<javaVersion>1.7</javaVersion>
<!-- Change Bukkit Version HERE! --> <!-- Change Bukkit Version HERE! -->
<bukkitVersion>1.9-pre1-SNAPSHOT</bukkitVersion> <bukkitVersion>1.9-SNAPSHOT</bukkitVersion>
</properties> </properties>
<!-- Jenkins profile (add the real buildNumber to the version string) -->
<profiles> <profiles>
<profile> <profile>
<id>jenkins</id> <id>jenkins</id>
@ -84,33 +87,21 @@
<testSourceDirectory>src/test/java</testSourceDirectory> <testSourceDirectory>src/test/java</testSourceDirectory>
<resources> <resources>
<resource>
<targetPath>.</targetPath>
<filtering>true</filtering>
<directory>src/main/resources/</directory>
<includes>
<include>plugin.yml</include>
</includes>
</resource>
<resource>
<targetPath>.</targetPath>
<filtering>true</filtering>
<directory>src/main/resources/</directory>
<includes>
<include>email.html</include>
<include>welcome.txt</include>
</includes>
</resource>
<resource> <resource>
<targetPath>.</targetPath> <targetPath>.</targetPath>
<filtering>false</filtering> <filtering>false</filtering>
<directory>.</directory>
<includes>
<include>LICENSE</include>
</includes>
</resource>
<resource>
<targetPath>.</targetPath>
<filtering>true</filtering>
<directory>src/main/resources/</directory> <directory>src/main/resources/</directory>
<includes> <includes>
<include>*.yml</include> <include>*</include>
</includes> </includes>
<excludes>
<exclude>plugin.yml</exclude>
</excludes>
</resource> </resource>
<resource> <resource>
<targetPath>./messages/</targetPath> <targetPath>./messages/</targetPath>
@ -128,15 +119,28 @@
</testResources> </testResources>
<plugins> <plugins>
<!-- Maven Java Compiler -->
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version> <version>3.5.1</version>
<configuration> <configuration>
<source>1.7</source> <source>${jdkVersion}</source>
<target>${javaVersion}</target> <target>${jdkVersion}</target>
<testSource>${testJreVersion}</testSource>
<testTarget>${testJreVersion}</testTarget>
</configuration> </configuration>
</plugin> </plugin>
<!-- Test Plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<configuration>
<argLine>-Dfile.encoding=${projectEncoding} ${argLine}</argLine>
</configuration>
</plugin>
<!-- Libs Shading and Relocation -->
<plugin> <plugin>
<!--Relocate all lib we use in order to fix class loading errors if we use different versions <!--Relocate all lib we use in order to fix class loading errors if we use different versions
than already loaded libs (i.e. by Mojang -> gson)--> than already loaded libs (i.e. by Mojang -> gson)-->
@ -161,33 +165,11 @@
</excludes> </excludes>
</artifactSet> </artifactSet>
<relocations> <relocations>
<!--We use a newer version of gson so include it to the jar and reference to the new version--> <!-- We use a newer version of gson so we need to include it! -->
<relocation> <relocation>
<pattern>com.google.gson</pattern> <pattern>com.google.gson</pattern>
<shadedPattern>fr.xephi.authme.libs.google</shadedPattern> <shadedPattern>fr.xephi.authme.libs.google</shadedPattern>
</relocation> </relocation>
<relocation>
<pattern>org.mcstats</pattern>
<shadedPattern>fr.xephi.authme</shadedPattern>
</relocation>
<!--
<relocation>
<pattern>org.apache</pattern>
<shadedPattern>fr.xephi.authme.libs.apache</shadedPattern>
</relocation>
<relocation>
<pattern>javax.mail</pattern>
<shadedPattern>fr.xephi.authme.libs.javax.mail</shadedPattern>
</relocation>
<relocation>
<pattern>javax.activation</pattern>
<shadedPattern>fr.xephi.authme.libs.javax.activation</shadedPattern>
</relocation>
<relocation>
<pattern>com.sun</pattern>
<shadedPattern>fr.xephi.authme.libs.sun</shadedPattern>
</relocation>
-->
<relocation> <relocation>
<pattern>com.zaxxer.hikari</pattern> <pattern>com.zaxxer.hikari</pattern>
<shadedPattern>fr.xephi.authme.libs.hikari</shadedPattern> <shadedPattern>fr.xephi.authme.libs.hikari</shadedPattern>
@ -204,6 +186,11 @@
<pattern>net.ricecode.similarity</pattern> <pattern>net.ricecode.similarity</pattern>
<shadedPattern>fr.xephi.authme.libs.similarity</shadedPattern> <shadedPattern>fr.xephi.authme.libs.similarity</shadedPattern>
</relocation> </relocation>
<!-- MCStats.org metrics -->
<relocation>
<pattern>org.mcstats</pattern>
<shadedPattern>fr.xephi.authme</shadedPattern>
</relocation>
</relocations> </relocations>
<outputFile>target/${jarName}-spigot.jar</outputFile> <outputFile>target/${jarName}-spigot.jar</outputFile>
</configuration> </configuration>
@ -215,34 +202,12 @@
<goal>shade</goal> <goal>shade</goal>
</goals> </goals>
<configuration> <configuration>
<!--Include all google libraries, because they are not avaialbe before 1.8--> <!-- Include all google libraries, because they are not available before 1.8 -->
<relocations> <relocations>
<relocation> <relocation>
<pattern>com.google</pattern> <pattern>com.google</pattern>
<shadedPattern>fr.xephi.authme.libs.google</shadedPattern> <shadedPattern>fr.xephi.authme.libs.google</shadedPattern>
</relocation> </relocation>
<relocation>
<pattern>org.mcstats</pattern>
<shadedPattern>fr.xephi.authme</shadedPattern>
</relocation>
<!--
<relocation>
<pattern>org.apache</pattern>
<shadedPattern>fr.xephi.authme.libs.apache</shadedPattern>
</relocation>
<relocation>
<pattern>javax.mail</pattern>
<shadedPattern>fr.xephi.authme.libs.javax.mail</shadedPattern>
</relocation>
<relocation>
<pattern>javax.activation</pattern>
<shadedPattern>fr.xephi.authme.libs.javax.activation</shadedPattern>
</relocation>
<relocation>
<pattern>com.sun</pattern>
<shadedPattern>fr.xephi.authme.libs.sun</shadedPattern>
</relocation>
-->
<relocation> <relocation>
<pattern>com.zaxxer.hikari</pattern> <pattern>com.zaxxer.hikari</pattern>
<shadedPattern>fr.xephi.authme.libs.hikari</shadedPattern> <shadedPattern>fr.xephi.authme.libs.hikari</shadedPattern>
@ -259,16 +224,22 @@
<pattern>net.ricecode.similarity</pattern> <pattern>net.ricecode.similarity</pattern>
<shadedPattern>fr.xephi.authme.libs.similarity</shadedPattern> <shadedPattern>fr.xephi.authme.libs.similarity</shadedPattern>
</relocation> </relocation>
<!-- MCStats.org metrics -->
<relocation>
<pattern>org.mcstats</pattern>
<shadedPattern>fr.xephi.authme</shadedPattern>
</relocation>
</relocations> </relocations>
<outputFile>target/${jarName}-legacy.jar</outputFile> <outputFile>target/${jarName}-legacy.jar</outputFile>
</configuration> </configuration>
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<!-- Test coverage -->
<plugin> <plugin>
<groupId>org.jacoco</groupId> <groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId> <artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.5.201505241946</version> <version>0.7.6.201602180812</version>
<executions> <executions>
<execution> <execution>
<id>prepare-agent</id> <id>prepare-agent</id>
@ -278,11 +249,12 @@
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<!-- Coveralls data -->
<plugin> <plugin>
<groupId>org.eluder.coveralls</groupId> <groupId>org.eluder.coveralls</groupId>
<artifactId>coveralls-maven-plugin</artifactId> <artifactId>coveralls-maven-plugin</artifactId>
<version>4.1.0</version> <version>4.1.0</version>
<!-- Token is provided by mvn command --> <!-- The secret token is provided by console! -->
</plugin> </plugin>
<!-- Javadocs settings --> <!-- Javadocs settings -->
<plugin> <plugin>
@ -292,7 +264,10 @@
<configuration> <configuration>
<charset>UTF-8</charset> <charset>UTF-8</charset>
<docencoding>UTF-8</docencoding> <docencoding>UTF-8</docencoding>
<dependencyLocationsEnabled>false</dependencyLocationsEnabled>
<docfilessubdirs>true</docfilessubdirs> <docfilessubdirs>true</docfilessubdirs>
<show>public</show>
<failOnError>false</failOnError>
</configuration> </configuration>
</plugin> </plugin>
</plugins> </plugins>
@ -305,10 +280,10 @@
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots</url> <url>https://hub.spigotmc.org/nexus/content/repositories/snapshots</url>
</repository> </repository>
<!-- EssentialsX Repo --> <!-- Essentials Repo -->
<repository> <repository>
<id>ess-repo</id> <id>ess-repo</id>
<url>http://ci.drtshock.net/plugin/repository/everything</url> <url>http://repo.ess3.net/content/groups/essentials</url>
</repository> </repository>
<!-- CombatTagPlus Repo --> <!-- CombatTagPlus Repo -->
@ -359,7 +334,7 @@
<dependency> <dependency>
<groupId>com.zaxxer</groupId> <groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId> <artifactId>HikariCP</artifactId>
<version>2.4.3</version> <version>2.4.5-SNAPSHOT</version>
<scope>compile</scope> <scope>compile</scope>
<exclusions> <exclusions>
<exclusion> <exclusion>
@ -372,7 +347,7 @@
<dependency> <dependency>
<groupId>org.slf4j</groupId> <groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId> <artifactId>slf4j-jdk14</artifactId>
<version>1.7.16</version> <version>1.7.18</version>
<scope>compile</scope> <scope>compile</scope>
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
@ -413,7 +388,7 @@
<dependency> <dependency>
<groupId>com.google.code.gson</groupId> <groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId> <artifactId>gson</artifactId>
<version>2.6.1</version> <version>2.6.2</version>
<scope>compile</scope> <scope>compile</scope>
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
@ -664,16 +639,20 @@
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
<!-- EssentialsX plugin, http://www.spigotmc.org/resources/essentialsx.9089/ --> <!-- Essentials plugin -->
<dependency> <dependency>
<groupId>net.ess3</groupId> <groupId>net.ess3</groupId>
<artifactId>EssentialsX</artifactId> <artifactId>Essentials</artifactId>
<version>2.0.1-SNAPSHOT</version> <version>2.13-SNAPSHOT</version>
<scope>provided</scope> <scope>provided</scope>
<exclusions> <exclusions>
<exclusion> <exclusion>
<groupId>org.spigotmc</groupId> <groupId>org.bukkit</groupId>
<artifactId>spigot-api</artifactId> <artifactId>bukkit</artifactId>
</exclusion>
<exclusion>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
</exclusion> </exclusion>
</exclusions> </exclusions>
<optional>true</optional> <optional>true</optional>
@ -683,7 +662,7 @@
<dependency> <dependency>
<groupId>net.minelink</groupId> <groupId>net.minelink</groupId>
<artifactId>CombatTagPlus</artifactId> <artifactId>CombatTagPlus</artifactId>
<version>1.2.1-SNAPSHOT</version> <version>1.2.2-SNAPSHOT</version>
<scope>provided</scope> <scope>provided</scope>
<exclusions> <exclusions>
<exclusion> <exclusion>

View File

@ -42,14 +42,15 @@ import fr.xephi.authme.output.Messages;
import fr.xephi.authme.permission.PermissionsManager; import fr.xephi.authme.permission.PermissionsManager;
import fr.xephi.authme.permission.PlayerStatePermission; import fr.xephi.authme.permission.PlayerStatePermission;
import fr.xephi.authme.process.Management; import fr.xephi.authme.process.Management;
import fr.xephi.authme.process.ProcessService;
import fr.xephi.authme.security.PasswordSecurity; import fr.xephi.authme.security.PasswordSecurity;
import fr.xephi.authme.security.crypts.SHA256; import fr.xephi.authme.security.crypts.SHA256;
import fr.xephi.authme.settings.NewSetting; import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.OtherAccounts;
import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.SettingsMigrationService; import fr.xephi.authme.settings.SettingsMigrationService;
import fr.xephi.authme.settings.Spawn; import fr.xephi.authme.settings.Spawn;
import fr.xephi.authme.settings.properties.DatabaseSettings; import fr.xephi.authme.settings.properties.DatabaseSettings;
import fr.xephi.authme.settings.properties.EmailSettings;
import fr.xephi.authme.settings.properties.HooksSettings; import fr.xephi.authme.settings.properties.HooksSettings;
import fr.xephi.authme.settings.properties.PluginSettings; import fr.xephi.authme.settings.properties.PluginSettings;
import fr.xephi.authme.settings.properties.RestrictionSettings; import fr.xephi.authme.settings.properties.RestrictionSettings;
@ -64,7 +65,6 @@ import org.apache.logging.log4j.LogManager;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Server; import org.bukkit.Server;
import org.bukkit.World;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -76,6 +76,7 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.net.URL; import java.net.URL;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.Collection; import java.util.Collection;
import java.util.Date; import java.util.Date;
@ -104,15 +105,14 @@ public class AuthMe extends JavaPlugin {
// Private Instances // Private Instances
private static AuthMe plugin; private static AuthMe plugin;
private static Server server; private static Server server;
private Management management; /*
private CommandHandler commandHandler = null; * Maps and stuff
private PermissionsManager permsMan = null; * TODO: Clean up and Move into a manager
private NewSetting newSettings; */
private Messages messages; public final ConcurrentHashMap<String, BukkitTask> sessions = new ConcurrentHashMap<>();
private JsonCache playerBackup; public final ConcurrentHashMap<String, Integer> captcha = new ConcurrentHashMap<>();
private PasswordSecurity passwordSecurity; public final ConcurrentHashMap<String, String> cap = new ConcurrentHashMap<>();
private DataSource database; public final ConcurrentHashMap<String, String> realIp = new ConcurrentHashMap<>();
/* /*
* Public Instances * Public Instances
* TODO #432: Encapsulation * TODO #432: Encapsulation
@ -120,9 +120,7 @@ public class AuthMe extends JavaPlugin {
public NewAPI api; public NewAPI api;
public SendMailSSL mail; public SendMailSSL mail;
public DataManager dataManager; public DataManager dataManager;
public OtherAccounts otherAccounts;
public Location essentialsSpawn; public Location essentialsSpawn;
/* /*
* Plugin Hooks * Plugin Hooks
* TODO: Move into modules * TODO: Move into modules
@ -133,15 +131,14 @@ public class AuthMe extends JavaPlugin {
public AuthMeInventoryPacketAdapter inventoryProtector; public AuthMeInventoryPacketAdapter inventoryProtector;
public AuthMeTabCompletePacketAdapter tabComplete; public AuthMeTabCompletePacketAdapter tabComplete;
public AuthMeTablistPacketAdapter tablistHider; public AuthMeTablistPacketAdapter tablistHider;
private Management management;
/* private CommandHandler commandHandler = null;
* Maps and stuff private PermissionsManager permsMan = null;
* TODO: Clean up and Move into a manager private NewSetting newSettings;
*/ private Messages messages;
public final ConcurrentHashMap<String, BukkitTask> sessions = new ConcurrentHashMap<>(); private JsonCache playerBackup;
public final ConcurrentHashMap<String, Integer> captcha = new ConcurrentHashMap<>(); private PasswordSecurity passwordSecurity;
public final ConcurrentHashMap<String, String> cap = new ConcurrentHashMap<>(); private DataSource database;
public final ConcurrentHashMap<String, String> realIp = new ConcurrentHashMap<>();
/** /**
* Get the plugin's instance. * Get the plugin's instance.
@ -259,9 +256,6 @@ public class AuthMe extends JavaPlugin {
permsMan = initializePermissionsManager(); permsMan = initializePermissionsManager();
commandHandler = initializeCommandHandler(permsMan, messages, passwordSecurity, newSettings); commandHandler = initializeCommandHandler(permsMan, messages, passwordSecurity, newSettings);
// Setup otherAccounts file
this.otherAccounts = OtherAccounts.getInstance();
// Set up Metrics // Set up Metrics
MetricsStarter.setupMetrics(plugin, newSettings); MetricsStarter.setupMetrics(plugin, newSettings);
@ -306,7 +300,8 @@ public class AuthMe extends JavaPlugin {
setupApi(); setupApi();
// Set up the management // Set up the management
management = new Management(this, newSettings); ProcessService processService = new ProcessService(newSettings, messages, this);
management = new Management(this, processService, database, PlayerCache.getInstance());
// Set up the BungeeCord hook // Set up the BungeeCord hook
setupBungeeCordHook(); setupBungeeCordHook();
@ -494,11 +489,41 @@ public class AuthMe extends JavaPlugin {
if (newSettings != null) { if (newSettings != null) {
new PerformBackup(plugin, newSettings).doBackup(PerformBackup.BackupCause.STOP); new PerformBackup(plugin, newSettings).doBackup(PerformBackup.BackupCause.STOP);
} }
new Thread(new Runnable() {
@Override
public void run() {
List<Integer> pendingTasks = new ArrayList<>();
for (BukkitTask pendingTask : getServer().getScheduler().getPendingTasks()) {
if (pendingTask.getOwner().equals(plugin) && !pendingTask.isSync()) {
pendingTasks.add(pendingTask.getTaskId());
}
}
ConsoleLogger.info("Waiting for " + pendingTasks.size() + " tasks to finish");
int progress = 0;
for (int taskId : pendingTasks) {
int maxTries = 5;
while (getServer().getScheduler().isCurrentlyRunning(taskId)) {
if (maxTries <= 0) {
ConsoleLogger.info("Async task " + taskId + " times out after to many tries");
break;
}
try {
Thread.sleep(1000);
} catch (InterruptedException ignored) {
}
maxTries--;
}
progress++;
ConsoleLogger.info("Progress: " + progress + " / " + pendingTasks.size());
}
if (database != null) {
database.close();
}
}
}, "AuthMe-DataSource#close").start();
// Close the database // Close the database
if (database != null) {
database.close();
}
// Disabled correctly // Disabled correctly
ConsoleLogger.info("AuthMe " + this.getDescription().getVersion() + " disabled!"); ConsoleLogger.info("AuthMe " + this.getDescription().getVersion() + " disabled!");
@ -518,7 +543,10 @@ public class AuthMe extends JavaPlugin {
* Sets up the data source. * Sets up the data source.
* *
* @param settings The settings instance * @param settings The settings instance
*
* @see AuthMe#database * @see AuthMe#database
* @throws ClassNotFoundException if no driver could be found for the datasource
* @throws SQLException when initialization of a SQL datasource failed
*/ */
public void setupDatabase(NewSetting settings) throws ClassNotFoundException, SQLException { public void setupDatabase(NewSetting settings) throws ClassNotFoundException, SQLException {
if (this.database != null) { if (this.database != null) {
@ -653,6 +681,7 @@ public class AuthMe extends JavaPlugin {
ConsoleLogger.showError("WARNING! The protectInventory feature requires ProtocolLib! Disabling it..."); ConsoleLogger.showError("WARNING! The protectInventory feature requires ProtocolLib! Disabling it...");
Settings.protectInventoryBeforeLogInEnabled = false; Settings.protectInventoryBeforeLogInEnabled = false;
newSettings.setProperty(RestrictionSettings.PROTECT_INVENTORY_BEFORE_LOGIN, false); newSettings.setProperty(RestrictionSettings.PROTECT_INVENTORY_BEFORE_LOGIN, false);
newSettings.save();
} }
return; return;
} }
@ -667,14 +696,14 @@ public class AuthMe extends JavaPlugin {
if (newSettings.getProperty(RestrictionSettings.DENY_TABCOMPLETE_BEFORE_LOGIN) && tabComplete == null) { if (newSettings.getProperty(RestrictionSettings.DENY_TABCOMPLETE_BEFORE_LOGIN) && tabComplete == null) {
tabComplete = new AuthMeTabCompletePacketAdapter(this); tabComplete = new AuthMeTabCompletePacketAdapter(this);
tabComplete.register(); tabComplete.register();
} else if (inventoryProtector != null) { } else if (tabComplete != null) {
tabComplete.unregister(); tabComplete.unregister();
tabComplete = null; tabComplete = null;
} }
if (newSettings.getProperty(RestrictionSettings.HIDE_TABLIST_BEFORE_LOGIN) && tablistHider == null) { if (newSettings.getProperty(RestrictionSettings.HIDE_TABLIST_BEFORE_LOGIN) && tablistHider == null) {
tablistHider = new AuthMeTablistPacketAdapter(this); tablistHider = new AuthMeTablistPacketAdapter(this);
tablistHider.register(); tablistHider.register();
} else if (inventoryProtector != null) { } else if (tablistHider != null) {
tablistHider.unregister(); tablistHider.unregister();
tablistHider = null; tablistHider = null;
} }
@ -748,42 +777,6 @@ public class AuthMe extends JavaPlugin {
return Spawn.getInstance().getSpawnLocation(player); return Spawn.getInstance().getSpawnLocation(player);
} }
// Return the default spawn point of a world
private Location getDefaultSpawn(World world) {
return world.getSpawnLocation();
}
// Return the multiverse spawn point of a world
private Location getMultiverseSpawn(World world) {
if (multiverse != null && Settings.multiverse) {
try {
return multiverse.getMVWorldManager().getMVWorld(world).getSpawnLocation();
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
// Return the essentials spawn point
private Location getEssentialsSpawn() {
if (essentialsSpawn != null) {
return essentialsSpawn;
}
return null;
}
// Return the AuthMe spawn point
private Location getAuthMeSpawn(Player player) {
if ((!database.isAuthAvailable(player.getName().toLowerCase()) || !player.hasPlayedBefore())
&& (Spawn.getInstance().getFirstSpawn() != null)) {
return Spawn.getInstance().getFirstSpawn();
} else if (Spawn.getInstance().getSpawn() != null) {
return Spawn.getInstance().getSpawn();
}
return player.getWorld().getSpawnLocation();
}
private void scheduleRecallEmailTask() { private void scheduleRecallEmailTask() {
if (!newSettings.getProperty(RECALL_PLAYERS)) { if (!newSettings.getProperty(RECALL_PLAYERS)) {
return; return;
@ -793,7 +786,7 @@ public class AuthMe extends JavaPlugin {
public void run() { public void run() {
for (PlayerAuth auth : database.getLoggedPlayers()) { for (PlayerAuth auth : database.getLoggedPlayers()) {
String email = auth.getEmail(); String email = auth.getEmail();
if (email == null || email.isEmpty() || email.equalsIgnoreCase("your@email.com")) { if (StringUtils.isEmpty(email) || email.equalsIgnoreCase("your@email.com")) {
Player player = Utils.getPlayer(auth.getRealName()); Player player = Utils.getPlayer(auth.getRealName());
if (player != null) { if (player != null) {
messages.send(player, MessageKey.ADD_EMAIL_MESSAGE); messages.send(player, MessageKey.ADD_EMAIL_MESSAGE);
@ -801,7 +794,7 @@ public class AuthMe extends JavaPlugin {
} }
} }
} }
}, 1, 1200 * Settings.delayRecall); }, 1, 1200 * newSettings.getProperty(EmailSettings.DELAY_RECALL));
} }
public String replaceAllInfo(String message, Player player) { public String replaceAllInfo(String message, Player player) {
@ -863,15 +856,6 @@ public class AuthMe extends JavaPlugin {
return count >= Settings.getMaxLoginPerIp; return count >= Settings.getMaxLoginPerIp;
} }
public boolean hasJoinedIp(String name, String ip) {
int count = 0;
for (Player player : Utils.getOnlinePlayers()) {
if (ip.equalsIgnoreCase(getIP(player)) && !player.getName().equalsIgnoreCase(name))
count++;
}
return count >= Settings.getMaxJoinPerIp;
}
/** /**
* Handle Bukkit commands. * Handle Bukkit commands.
* *

View File

@ -13,7 +13,10 @@ import fr.xephi.authme.security.crypts.HashedPassword;
import fr.xephi.authme.util.Utils; import fr.xephi.authme.util.Utils;
/** /**
* The current API of AuthMe. * The current API of AuthMe. Recommended method of retrieving the API object:
* <code>
* NewAPI authmeApi = NewAPI.getInstance();
* </code>
*/ */
public class NewAPI { public class NewAPI {
@ -23,7 +26,7 @@ public class NewAPI {
/** /**
* Constructor for NewAPI. * Constructor for NewAPI.
* *
* @param plugin AuthMe * @param plugin The AuthMe plugin instance
*/ */
public NewAPI(AuthMe plugin) { public NewAPI(AuthMe plugin) {
this.plugin = plugin; this.plugin = plugin;
@ -32,16 +35,17 @@ public class NewAPI {
/** /**
* Constructor for NewAPI. * Constructor for NewAPI.
* *
* @param server Server * @param server The server instance
*/ */
public NewAPI(Server server) { public NewAPI(Server server) {
this.plugin = (AuthMe) server.getPluginManager().getPlugin("AuthMe"); this.plugin = (AuthMe) server.getPluginManager().getPlugin("AuthMe");
} }
/** /**
* Hook into AuthMe * Get the API object for AuthMe.
* *
* @return The API object * @return The API object, or null if the AuthMe plugin instance could not be retrieved
* from the server environment
*/ */
public static NewAPI getInstance() { public static NewAPI getInstance() {
if (singleton != null) { if (singleton != null) {
@ -69,7 +73,6 @@ public class NewAPI {
* Return whether the given player is authenticated. * Return whether the given player is authenticated.
* *
* @param player The player to verify * @param player The player to verify
*
* @return true if the player is authenticated * @return true if the player is authenticated
*/ */
public boolean isAuthenticated(Player player) { public boolean isAuthenticated(Player player) {
@ -77,18 +80,22 @@ public class NewAPI {
} }
/** /**
* @param player a Player * Check whether the given player is an NPC.
* *
* @return true if player is a npc * @param player The player to verify
* @return true if the player is an npc
*/ */
public boolean isNPC(Player player) { public boolean isNPC(Player player) {
return Utils.isNPC(player); return Utils.isNPC(player);
} }
/** /**
* @param player a Player * Check whether the given player is unrestricted. For such players, AuthMe will not require
* them to authenticate.
* *
* @param player The player to verify
* @return true if the player is unrestricted * @return true if the player is unrestricted
* @see fr.xephi.authme.settings.properties.RestrictionSettings#UNRESTRICTED_NAMES
*/ */
public boolean isUnrestricted(Player player) { public boolean isUnrestricted(Player player) {
return Utils.isUnrestricted(player); return Utils.isUnrestricted(player);
@ -97,30 +104,21 @@ public class NewAPI {
/** /**
* Get the last location of a player. * Get the last location of a player.
* *
* @param player Player The player to process * @param player The player to process
*
* @return Location The location of the player * @return Location The location of the player
*/ */
public Location getLastLocation(Player player) { public Location getLastLocation(Player player) {
try { PlayerAuth auth = PlayerCache.getInstance().getAuth(player.getName());
PlayerAuth auth = PlayerCache.getInstance().getAuth(player.getName()); if (auth != null) {
return new Location(Bukkit.getWorld(auth.getWorld()), auth.getQuitLocX(), auth.getQuitLocY(), auth.getQuitLocZ());
if (auth != null) {
return new Location(Bukkit.getWorld(auth.getWorld()), auth.getQuitLocX(), auth.getQuitLocY(), auth.getQuitLocZ());
} else {
return null;
}
} catch (NullPointerException ex) {
return null;
} }
return null;
} }
/** /**
* Return whether the player is registered. * Return whether the player is registered.
* *
* @param playerName The player name to check * @param playerName The player name to check
*
* @return true if player is registered, false otherwise * @return true if player is registered, false otherwise
*/ */
public boolean isRegistered(String playerName) { public boolean isRegistered(String playerName) {
@ -133,7 +131,6 @@ public class NewAPI {
* *
* @param playerName The player to check the password for * @param playerName The player to check the password for
* @param passwordToCheck The password to check * @param passwordToCheck The password to check
*
* @return true if the password is correct, false otherwise * @return true if the password is correct, false otherwise
*/ */
public boolean checkPassword(String playerName, String passwordToCheck) { public boolean checkPassword(String playerName, String passwordToCheck) {
@ -141,11 +138,10 @@ public class NewAPI {
} }
/** /**
* Register a player. * Register a player with the given password.
* *
* @param playerName The player to register * @param playerName The player to register
* @param password The password to register the player with * @param password The password to register the player with
*
* @return true if the player was registered successfully * @return true if the player was registered successfully
*/ */
public boolean registerPlayer(String playerName, String password) { public boolean registerPlayer(String playerName, String password) {
@ -163,7 +159,7 @@ public class NewAPI {
} }
/** /**
* Force a player to login. * Force a player to login, i.e. the player is logged in without needing his password.
* *
* @param player The player to log in * @param player The player to log in
*/ */
@ -181,7 +177,7 @@ public class NewAPI {
} }
/** /**
* Force a player to register. * Register a player with the given password.
* *
* @param player The player to register * @param player The player to register
* @param password The password to use * @param password The password to use
@ -191,7 +187,7 @@ public class NewAPI {
} }
/** /**
* Force a player to unregister. * Unregister a player from AuthMe.
* *
* @param player The player to unregister * @param player The player to unregister
*/ */

View File

@ -8,7 +8,6 @@ import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer; import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer; import com.google.gson.JsonSerializer;
import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.ConsoleLogger;
@ -41,14 +40,8 @@ public class JsonCache {
return; return;
} }
String path; String name = player.getName().toLowerCase();
try { File file = new File(cacheDir, name + File.separator + "cache.json");
path = player.getUniqueId().toString();
} catch (Exception | Error e) {
path = player.getName().toLowerCase();
}
File file = new File(cacheDir, path + File.separator + "cache.json");
if (file.exists()) { if (file.exists()) {
return; return;
} }
@ -61,19 +54,13 @@ public class JsonCache {
Files.touch(file); Files.touch(file);
Files.write(data, file, Charsets.UTF_8); Files.write(data, file, Charsets.UTF_8);
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); ConsoleLogger.writeStackTrace(e);
} }
} }
public PlayerData readCache(Player player) { public PlayerData readCache(Player player) {
String path; String name = player.getName().toLowerCase();
try { File file = new File(cacheDir, name + File.separator + "cache.json");
path = player.getUniqueId().toString();
} catch (Exception | Error e) {
path = player.getName().toLowerCase();
}
File file = new File(cacheDir, path + File.separator + "cache.json");
if (!file.exists()) { if (!file.exists()) {
return null; return null;
} }
@ -81,20 +68,15 @@ public class JsonCache {
try { try {
String str = Files.toString(file, Charsets.UTF_8); String str = Files.toString(file, Charsets.UTF_8);
return gson.fromJson(str, PlayerData.class); return gson.fromJson(str, PlayerData.class);
} catch (Exception e) { } catch (IOException e) {
e.printStackTrace(); ConsoleLogger.writeStackTrace(e);
return null; return null;
} }
} }
public void removeCache(Player player) { public void removeCache(Player player) {
String path; String name = player.getName().toLowerCase();
try { File file = new File(cacheDir, name);
path = player.getUniqueId().toString();
} catch (Exception | Error e) {
path = player.getName().toLowerCase();
}
File file = new File(cacheDir, path);
if (file.exists()) { if (file.exists()) {
purgeDirectory(file); purgeDirectory(file);
if (!file.delete()) { if (!file.delete()) {
@ -104,19 +86,15 @@ public class JsonCache {
} }
public boolean doesCacheExist(Player player) { public boolean doesCacheExist(Player player) {
String path; String name = player.getName().toLowerCase();
try { File file = new File(cacheDir, name + File.separator + "cache.json");
path = player.getUniqueId().toString();
} catch (Exception | Error e) {
path = player.getName().toLowerCase();
}
File file = new File(cacheDir, path + File.separator + "cache.json");
return file.exists(); return file.exists();
} }
private class PlayerDataDeserializer implements JsonDeserializer<PlayerData> { private class PlayerDataDeserializer implements JsonDeserializer<PlayerData> {
@Override @Override
public PlayerData deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException { public PlayerData deserialize(JsonElement jsonElement, Type type,
JsonDeserializationContext context) {
JsonObject jsonObject = jsonElement.getAsJsonObject(); JsonObject jsonObject = jsonElement.getAsJsonObject();
if (jsonObject == null) { if (jsonObject == null) {
return null; return null;
@ -143,7 +121,7 @@ public class JsonCache {
private class PlayerDataSerializer implements JsonSerializer<PlayerData> { private class PlayerDataSerializer implements JsonSerializer<PlayerData> {
@Override @Override
public JsonElement serialize(PlayerData playerData, Type type, public JsonElement serialize(PlayerData playerData, Type type,
JsonSerializationContext jsonSerializationContext) { JsonSerializationContext context) {
JsonObject jsonObject = new JsonObject(); JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("group", playerData.getGroup()); jsonObject.addProperty("group", playerData.getGroup());
jsonObject.addProperty("operator", playerData.getOperator()); jsonObject.addProperty("operator", playerData.getOperator());

View File

@ -92,7 +92,7 @@ public final class CommandInitializer {
.description("Enforce login player") .description("Enforce login player")
.detailedDescription("Enforce the specified player to login.") .detailedDescription("Enforce the specified player to login.")
.withArgument("player", "Online player name", true) .withArgument("player", "Online player name", true)
.permissions(OP_ONLY, PlayerPermission.CAN_LOGIN_BE_FORCED) .permissions(OP_ONLY, AdminPermission.FORCE_LOGIN)
.executableCommand(new ForceLoginCommand()) .executableCommand(new ForceLoginCommand())
.build(); .build();

View File

@ -22,8 +22,8 @@ public class RegisterAdminCommand implements ExecutableCommand {
public void executeCommand(final CommandSender sender, List<String> arguments, public void executeCommand(final CommandSender sender, List<String> arguments,
final CommandService commandService) { final CommandService commandService) {
// Get the player name and password // Get the player name and password
final String playerName = arguments.get(0).toLowerCase(); final String playerName = arguments.get(0);
final String playerPass = arguments.get(1).toLowerCase(); final String playerPass = arguments.get(1);
final String playerNameLowerCase = playerName.toLowerCase(); final String playerNameLowerCase = playerName.toLowerCase();
final String playerPassLowerCase = playerPass.toLowerCase(); final String playerPassLowerCase = playerPass.toLowerCase();

View File

@ -1,14 +1,5 @@
package fr.xephi.authme.command.executable.authme; package fr.xephi.authme.command.executable.authme;
import java.util.List;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.scheduler.BukkitTask;
import fr.xephi.authme.AuthMe; import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.PlayerCache; import fr.xephi.authme.cache.auth.PlayerCache;
@ -20,6 +11,14 @@ import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.task.MessageTask; import fr.xephi.authme.task.MessageTask;
import fr.xephi.authme.task.TimeoutTask; import fr.xephi.authme.task.TimeoutTask;
import fr.xephi.authme.util.Utils; import fr.xephi.authme.util.Utils;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.scheduler.BukkitTask;
import java.util.List;
/** /**
* Admin command to unregister a player. * Admin command to unregister a player.
@ -55,19 +54,20 @@ public class UnregisterAdminCommand implements ExecutableCommand {
if (target != null && target.isOnline()) { if (target != null && target.isOnline()) {
Utils.teleportToSpawn(target); Utils.teleportToSpawn(target);
LimboCache.getInstance().addLimboPlayer(target); LimboCache.getInstance().addLimboPlayer(target);
int delay = Settings.getRegistrationTimeout * 20; int timeOut = Settings.getRegistrationTimeout * 20;
int interval = Settings.getWarnMessageInterval; int interval = Settings.getWarnMessageInterval;
BukkitScheduler scheduler = sender.getServer().getScheduler(); BukkitScheduler scheduler = sender.getServer().getScheduler();
if (delay != 0) { if (timeOut != 0) {
BukkitTask id = scheduler.runTaskLaterAsynchronously(plugin, new TimeoutTask(plugin, playerNameLowerCase, target), delay); BukkitTask id = scheduler.runTaskLater(plugin, new TimeoutTask(plugin, playerNameLowerCase, target), timeOut);
LimboCache.getInstance().getLimboPlayer(playerNameLowerCase).setTimeoutTaskId(id); LimboCache.getInstance().getLimboPlayer(playerNameLowerCase).setTimeoutTaskId(id);
} }
LimboCache.getInstance().getLimboPlayer(playerNameLowerCase).setMessageTaskId( LimboCache.getInstance().getLimboPlayer(playerNameLowerCase).setMessageTaskId(
scheduler.runTaskAsynchronously(plugin, scheduler.runTask(
new MessageTask(plugin, playerNameLowerCase, commandService.retrieveMessage(MessageKey.REGISTER_MESSAGE), interval))); plugin, new MessageTask(plugin, playerNameLowerCase, MessageKey.REGISTER_MESSAGE, interval)
)
);
if (Settings.applyBlindEffect) { if (Settings.applyBlindEffect) {
target.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, target.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, timeOut, 2));
Settings.getRegistrationTimeout * 20, 2));
} }
commandService.send(target, MessageKey.UNREGISTERED_SUCCESS); commandService.send(target, MessageKey.UNREGISTERED_SUCCESS);
} }

View File

@ -3,14 +3,14 @@ package fr.xephi.authme.command.executable.authme;
import fr.xephi.authme.AuthMe; import fr.xephi.authme.AuthMe;
import fr.xephi.authme.command.CommandService; import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.command.ExecutableCommand;
import org.bukkit.Bukkit; import static fr.xephi.authme.settings.properties.PluginSettings.HELP_HEADER;
import org.bukkit.ChatColor; import fr.xephi.authme.util.Utils;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.List; import java.util.List;
import static fr.xephi.authme.settings.properties.PluginSettings.HELP_HEADER; import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
public class VersionCommand implements ExecutableCommand { public class VersionCommand implements ExecutableCommand {
@ -73,7 +73,7 @@ public class VersionCommand implements ExecutableCommand {
private static boolean isPlayerOnline(String minecraftName) { private static boolean isPlayerOnline(String minecraftName) {
// Note ljacqu 20151121: Generally you should use Utils#getOnlinePlayers to retrieve the list of online players. // Note ljacqu 20151121: Generally you should use Utils#getOnlinePlayers to retrieve the list of online players.
// If it's only used in a for-each loop such as here, it's fine. For other purposes, go through the Utils class. // If it's only used in a for-each loop such as here, it's fine. For other purposes, go through the Utils class.
for (Player player : Bukkit.getOnlinePlayers()) { for (Player player : Utils.getOnlinePlayers()) {
if (player.getName().equalsIgnoreCase(minecraftName)) { if (player.getName().equalsIgnoreCase(minecraftName)) {
return true; return true;
} }

View File

@ -3,39 +3,51 @@ package fr.xephi.authme.converter;
import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.datasource.DataSourceType; import fr.xephi.authme.datasource.FlatFile;
import fr.xephi.authme.datasource.SQLite; import fr.xephi.authme.util.StringUtils;
import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.properties.DatabaseSettings; import java.util.ArrayList;
import java.sql.SQLException; import java.util.List;
/** /**
* Mandatory migration from the deprecated flat file datasource to SQLite. * Mandatory migration from the deprecated flat file datasource to SQLite.
*/ */
public class ForceFlatToSqlite { public class ForceFlatToSqlite implements Converter {
private final DataSource database; private final DataSource source;
private final NewSetting settings; private final DataSource destination;
public ForceFlatToSqlite(DataSource database, NewSetting settings) { /**
this.database = database; * Constructor.
this.settings = settings; *
* @param source The datasource to convert (flatfile)
* @param destination The datasource to copy the data to (sqlite)
*/
public ForceFlatToSqlite(FlatFile source, DataSource destination) {
this.source = source;
this.destination = destination;
} }
public DataSource run() { /**
try { * Perform the conversion.
DataSource sqlite = new SQLite(settings); */
for (PlayerAuth auth : database.getAllAuths()) { @Override
auth.setRealName("Player"); public void run() {
sqlite.saveAuth(auth); List<String> skippedPlayers = new ArrayList<>();
for (PlayerAuth auth : source.getAllAuths()) {
if (destination.isAuthAvailable(auth.getNickname())) {
skippedPlayers.add(auth.getNickname());
} else {
destination.saveAuth(auth);
destination.updateQuitLoc(auth);
} }
settings.setProperty(DatabaseSettings.BACKEND, DataSourceType.SQLITE);
settings.save();
ConsoleLogger.info("Database successfully converted to sqlite!");
return sqlite;
} catch (SQLException | ClassNotFoundException e) {
ConsoleLogger.logException("Could not convert from Flatfile to SQLite:", e);
} }
return null;
if (!skippedPlayers.isEmpty()) {
ConsoleLogger.showError("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());
} }
} }

View File

@ -4,14 +4,19 @@ import com.google.common.base.Optional;
import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader; import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache; import com.google.common.cache.LoadingCache;
import com.google.common.cache.RemovalListener; import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.cache.RemovalNotification; import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.cache.auth.PlayerCache; import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.security.crypts.HashedPassword; import fr.xephi.authme.security.crypts.HashedPassword;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/** /**
@ -20,6 +25,7 @@ public class CacheDataSource implements DataSource {
private final DataSource source; private final DataSource source;
private final LoadingCache<String, Optional<PlayerAuth>> cachedAuths; private final LoadingCache<String, Optional<PlayerAuth>> cachedAuths;
private final ListeningExecutorService executorService;
/** /**
* Constructor for CacheDataSource. * Constructor for CacheDataSource.
@ -27,25 +33,35 @@ public class CacheDataSource implements DataSource {
* @param src DataSource * @param src DataSource
*/ */
public CacheDataSource(DataSource src) { public CacheDataSource(DataSource src) {
this.source = src; source = src;
this.cachedAuths = CacheBuilder.newBuilder() executorService = MoreExecutors.listeningDecorator(
.expireAfterWrite(8, TimeUnit.MINUTES) Executors.newCachedThreadPool(new ThreadFactoryBuilder()
.removalListener(new RemovalListener<String, Optional<PlayerAuth>>() { .setDaemon(true)
.setNameFormat("AuthMe-CacheLoader")
.build())
);
cachedAuths = CacheBuilder.newBuilder()
.refreshAfterWrite(8, TimeUnit.MINUTES)
.build(new CacheLoader<String, Optional<PlayerAuth>>() {
@Override @Override
public void onRemoval(RemovalNotification<String, Optional<PlayerAuth>> removalNotification) { public Optional<PlayerAuth> load(String key) {
String name = removalNotification.getKey(); return Optional.fromNullable(source.getAuth(key));
if (PlayerCache.getInstance().isAuthenticated(name)) {
cachedAuths.getUnchecked(name);
}
} }
})
.build( @Override
new CacheLoader<String, Optional<PlayerAuth>>() { public ListenableFuture<Optional<PlayerAuth>> reload(final String key, Optional<PlayerAuth> oldValue) {
@Override return executorService.submit(new Callable<Optional<PlayerAuth>>() {
public Optional<PlayerAuth> load(String key) { @Override
return Optional.fromNullable(source.getAuth(key)); public Optional<PlayerAuth> call() {
} return load(key);
}); }
});
}
});
}
public LoadingCache<String, Optional<PlayerAuth>> getCachedAuths() {
return cachedAuths;
} }
@Override @Override
@ -137,6 +153,13 @@ public class CacheDataSource implements DataSource {
@Override @Override
public synchronized void close() { public synchronized void close() {
source.close(); source.close();
cachedAuths.invalidateAll();
executorService.shutdown();
try {
executorService.awaitTermination(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
ConsoleLogger.writeStackTrace(e);
}
} }
@Override @Override
@ -201,12 +224,6 @@ public class CacheDataSource implements DataSource {
return source.getAccountsRegistered(); return source.getAccountsRegistered();
} }
@Override
public void updateName(final String oldOne, final String newOne) { // unused method
source.updateName(oldOne, newOne);
cachedAuths.invalidate(oldOne);
}
@Override @Override
public boolean updateRealName(String user, String realName) { public boolean updateRealName(String user, String realName) {
boolean result = source.updateRealName(user, realName); boolean result = source.updateRealName(user, realName);

View File

@ -169,14 +169,6 @@ public interface DataSource {
*/ */
int getAccountsRegistered(); int getAccountsRegistered();
/**
* Method updateName.
*
* @param oldOne String
* @param newOne String
*/
void updateName(String oldOne, String newOne);
boolean updateRealName(String user, String realName); boolean updateRealName(String user, String realName);
boolean updateIp(String user, String ip); boolean updateIp(String user, String ip);

View File

@ -1,5 +1,6 @@
package fr.xephi.authme.datasource; package fr.xephi.authme.datasource;
import com.google.common.annotations.VisibleForTesting;
import fr.xephi.authme.AuthMe; import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.cache.auth.PlayerAuth;
@ -42,7 +43,7 @@ public class FlatFile implements DataSource {
try { try {
source.createNewFile(); source.createNewFile();
} catch (IOException e) { } catch (IOException e) {
ConsoleLogger.showError(e.getMessage()); ConsoleLogger.logException("Cannot open flatfile", e);
if (Settings.isStopEnabled) { if (Settings.isStopEnabled) {
ConsoleLogger.showError("Can't use FLAT FILE... SHUTDOWN..."); ConsoleLogger.showError("Can't use FLAT FILE... SHUTDOWN...");
instance.getServer().shutdown(); instance.getServer().shutdown();
@ -50,10 +51,14 @@ public class FlatFile implements DataSource {
if (!Settings.isStopEnabled) { if (!Settings.isStopEnabled) {
instance.getServer().getPluginManager().disablePlugin(instance); instance.getServer().getPluginManager().disablePlugin(instance);
} }
e.printStackTrace();
} }
} }
@VisibleForTesting
public FlatFile(File source) {
this.source = source;
}
@Override @Override
public synchronized boolean isAuthAvailable(String user) { public synchronized boolean isAuthAvailable(String user) {
BufferedReader br = null; BufferedReader br = null;
@ -599,17 +604,9 @@ public class FlatFile implements DataSource {
return result; return result;
} }
@Override
public void updateName(String oldOne, String newOne) {
PlayerAuth auth = this.getAuth(oldOne);
auth.setNickname(newOne);
this.saveAuth(auth);
this.removeAuth(oldOne);
}
@Override @Override
public boolean updateRealName(String user, String realName) { public boolean updateRealName(String user, String realName) {
return false; throw new UnsupportedOperationException("Flat file no longer supported");
} }
@Override @Override
@ -626,33 +623,25 @@ public class FlatFile implements DataSource {
String line; String line;
while ((line = br.readLine()) != null) { while ((line = br.readLine()) != null) {
String[] args = line.split(":"); String[] args = line.split(":");
switch (args.length) { // We expect to encounter 2, 3, 4, 7, 8 or 9 fields. Ignore the line otherwise
case 2: if (args.length >= 2 && args.length != 5 && args.length != 6 && args.length <= 9) {
auths.add(new PlayerAuth(args[0], args[1], "192.168.0.1", 0, "your@email.com", args[0])); PlayerAuth.Builder builder = PlayerAuth.builder()
break; .name(args[0]).realName(args[0])
case 3: .password(args[1], null);
auths.add(new PlayerAuth(args[0], args[1], args[2], 0, "your@email.com", args[0])); if (args.length >= 3) builder.ip(args[2]);
break; if (args.length >= 4) builder.lastLogin(Long.parseLong(args[3]));
case 4: if (args.length >= 7) {
auths.add(new PlayerAuth(args[0], args[1], args[2], Long.parseLong(args[3]), "your@email.com", args[0])); builder.locX(Double.parseDouble(args[4]))
break; .locY(Double.parseDouble(args[5]))
case 7: .locZ(Double.parseDouble(args[6]));
auths.add(new PlayerAuth(args[0], args[1], args[2], Long.parseLong(args[3]), Double.parseDouble(args[4]), Double.parseDouble(args[5]), Double.parseDouble(args[6]), "unavailableworld", "your@email.com", args[0])); }
break; if (args.length >= 8) builder.locWorld(args[7]);
case 8: if (args.length >= 9) builder.email(args[8]);
auths.add(new PlayerAuth(args[0], args[1], args[2], Long.parseLong(args[3]), Double.parseDouble(args[4]), Double.parseDouble(args[5]), Double.parseDouble(args[6]), args[7], "your@email.com", args[0])); auths.add(builder.build());
break;
case 9:
auths.add(new PlayerAuth(args[0], args[1], args[2], Long.parseLong(args[3]), Double.parseDouble(args[4]), Double.parseDouble(args[5]), Double.parseDouble(args[6]), args[7], args[8], args[0]));
break;
} }
} }
} catch (FileNotFoundException ex) {
ConsoleLogger.showError(ex.getMessage());
return auths;
} catch (IOException ex) { } catch (IOException ex) {
ConsoleLogger.showError(ex.getMessage()); ConsoleLogger.logException("Error while getting auths from flatfile:", ex);
return auths;
} finally { } finally {
if (br != null) { if (br != null) {
try { try {
@ -666,7 +655,7 @@ public class FlatFile implements DataSource {
@Override @Override
public List<PlayerAuth> getLoggedPlayers() { public List<PlayerAuth> getLoggedPlayers() {
return new ArrayList<>(); throw new UnsupportedOperationException("Flat file no longer supported");
} }
@Override @Override

View File

@ -1,5 +1,6 @@
package fr.xephi.authme.datasource; package fr.xephi.authme.datasource;
import com.google.common.annotations.VisibleForTesting;
import com.zaxxer.hikari.HikariDataSource; import com.zaxxer.hikari.HikariDataSource;
import com.zaxxer.hikari.pool.HikariPool.PoolInitializationException; import com.zaxxer.hikari.pool.HikariPool.PoolInitializationException;
import fr.xephi.authme.AuthMe; import fr.xephi.authme.AuthMe;
@ -41,6 +42,10 @@ public class MySQL implements DataSource {
private final HashAlgorithm hashAlgorithm; private final HashAlgorithm hashAlgorithm;
private HikariDataSource ds; private HikariDataSource ds;
private final String phpBbPrefix;
private final int phpBbGroup;
private final String wordpressPrefix;
public MySQL(NewSetting settings) throws ClassNotFoundException, SQLException, PoolInitializationException { public MySQL(NewSetting settings) throws ClassNotFoundException, SQLException, PoolInitializationException {
this.host = settings.getProperty(DatabaseSettings.MYSQL_HOST); this.host = settings.getProperty(DatabaseSettings.MYSQL_HOST);
this.port = settings.getProperty(DatabaseSettings.MYSQL_PORT); this.port = settings.getProperty(DatabaseSettings.MYSQL_PORT);
@ -51,6 +56,9 @@ public class MySQL implements DataSource {
this.columnOthers = settings.getProperty(HooksSettings.MYSQL_OTHER_USERNAME_COLS); this.columnOthers = settings.getProperty(HooksSettings.MYSQL_OTHER_USERNAME_COLS);
this.col = new Columns(settings); this.col = new Columns(settings);
this.hashAlgorithm = settings.getProperty(SecuritySettings.PASSWORD_HASH); this.hashAlgorithm = settings.getProperty(SecuritySettings.PASSWORD_HASH);
this.phpBbPrefix = settings.getProperty(HooksSettings.PHPBB_TABLE_PREFIX);
this.phpBbGroup = settings.getProperty(HooksSettings.PHPBB_ACTIVATED_GROUP_ID);
this.wordpressPrefix = settings.getProperty(HooksSettings.WORDPRESS_TABLE_PREFIX);
// Set the connection arguments (and check if connection is ok) // Set the connection arguments (and check if connection is ok)
try { try {
@ -81,6 +89,7 @@ public class MySQL implements DataSource {
} }
} }
@VisibleForTesting
MySQL(NewSetting settings, HikariDataSource hikariDataSource) { MySQL(NewSetting settings, HikariDataSource hikariDataSource) {
this.host = settings.getProperty(DatabaseSettings.MYSQL_HOST); this.host = settings.getProperty(DatabaseSettings.MYSQL_HOST);
this.port = settings.getProperty(DatabaseSettings.MYSQL_PORT); this.port = settings.getProperty(DatabaseSettings.MYSQL_PORT);
@ -91,6 +100,9 @@ public class MySQL implements DataSource {
this.columnOthers = settings.getProperty(HooksSettings.MYSQL_OTHER_USERNAME_COLS); this.columnOthers = settings.getProperty(HooksSettings.MYSQL_OTHER_USERNAME_COLS);
this.col = new Columns(settings); this.col = new Columns(settings);
this.hashAlgorithm = settings.getProperty(SecuritySettings.PASSWORD_HASH); this.hashAlgorithm = settings.getProperty(SecuritySettings.PASSWORD_HASH);
this.phpBbPrefix = settings.getProperty(HooksSettings.PHPBB_TABLE_PREFIX);
this.phpBbGroup = settings.getProperty(HooksSettings.PHPBB_ACTIVATED_GROUP_ID);
this.wordpressPrefix = settings.getProperty(HooksSettings.WORDPRESS_TABLE_PREFIX);
ds = hikariDataSource; ds = hikariDataSource;
} }
@ -359,10 +371,10 @@ public class MySQL implements DataSource {
if (rs.next()) { if (rs.next()) {
int id = rs.getInt(col.ID); int id = rs.getInt(col.ID);
// Insert player in phpbb_user_group // Insert player in phpbb_user_group
sql = "INSERT INTO " + Settings.getPhpbbPrefix sql = "INSERT INTO " + phpBbPrefix
+ "user_group (group_id, user_id, group_leader, user_pending) VALUES (?,?,?,?);"; + "user_group (group_id, user_id, group_leader, user_pending) VALUES (?,?,?,?);";
pst2 = con.prepareStatement(sql); pst2 = con.prepareStatement(sql);
pst2.setInt(1, Settings.getPhpbbGroup); pst2.setInt(1, phpBbGroup);
pst2.setInt(2, id); pst2.setInt(2, id);
pst2.setInt(3, 0); pst2.setInt(3, 0);
pst2.setInt(4, 0); pst2.setInt(4, 0);
@ -380,7 +392,7 @@ public class MySQL implements DataSource {
sql = "UPDATE " + tableName + " SET " + tableName sql = "UPDATE " + tableName + " SET " + tableName
+ ".group_id=? WHERE " + col.NAME + "=?;"; + ".group_id=? WHERE " + col.NAME + "=?;";
pst2 = con.prepareStatement(sql); pst2 = con.prepareStatement(sql);
pst2.setInt(1, Settings.getPhpbbGroup); pst2.setInt(1, phpBbGroup);
pst2.setString(2, auth.getNickname()); pst2.setString(2, auth.getNickname());
pst2.executeUpdate(); pst2.executeUpdate();
pst2.close(); pst2.close();
@ -403,7 +415,7 @@ public class MySQL implements DataSource {
pst2.executeUpdate(); pst2.executeUpdate();
pst2.close(); pst2.close();
// Increment num_users // Increment num_users
sql = "UPDATE " + Settings.getPhpbbPrefix sql = "UPDATE " + phpBbPrefix
+ "config SET config_value = config_value + 1 WHERE config_name = 'num_users';"; + "config SET config_value = config_value + 1 WHERE config_name = 'num_users';";
pst2 = con.prepareStatement(sql); pst2 = con.prepareStatement(sql);
pst2.executeUpdate(); pst2.executeUpdate();
@ -417,7 +429,7 @@ public class MySQL implements DataSource {
rs = pst.executeQuery(); rs = pst.executeQuery();
if (rs.next()) { if (rs.next()) {
int id = rs.getInt(col.ID); int id = rs.getInt(col.ID);
sql = "INSERT INTO " + Settings.getWordPressPrefix + "usermeta (user_id, meta_key, meta_value) VALUES (?,?,?);"; sql = "INSERT INTO " + wordpressPrefix + "usermeta (user_id, meta_key, meta_value) VALUES (?,?,?);";
pst2 = con.prepareStatement(sql); pst2 = con.prepareStatement(sql);
// First Name // First Name
pst2.setInt(1, id); pst2.setInt(1, id);
@ -620,31 +632,32 @@ public class MySQL implements DataSource {
@Override @Override
public synchronized boolean removeAuth(String user) { public synchronized boolean removeAuth(String user) {
user = user.toLowerCase(); user = user.toLowerCase();
try (Connection con = getConnection()) { String sql = "DELETE FROM " + tableName + " WHERE " + col.NAME + "=?;";
String sql; PreparedStatement xfSelect = null;
PreparedStatement pst; PreparedStatement xfDelete = null;
try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
if (hashAlgorithm == HashAlgorithm.XFBCRYPT) { if (hashAlgorithm == HashAlgorithm.XFBCRYPT) {
sql = "SELECT " + col.ID + " FROM " + tableName + " WHERE " + col.NAME + "=?;"; sql = "SELECT " + col.ID + " FROM " + tableName + " WHERE " + col.NAME + "=?;";
pst = con.prepareStatement(sql); xfSelect = con.prepareStatement(sql);
pst.setString(1, user); xfSelect.setString(1, user);
ResultSet rs = pst.executeQuery(); try (ResultSet rs = xfSelect.executeQuery()) {
if (rs.next()) { if (rs.next()) {
int id = rs.getInt(col.ID); int id = rs.getInt(col.ID);
sql = "DELETE FROM xf_user_authenticate WHERE " + col.ID + "=?;"; sql = "DELETE FROM xf_user_authenticate WHERE " + col.ID + "=?;";
PreparedStatement st = con.prepareStatement(sql); xfDelete = con.prepareStatement(sql);
st.setInt(1, id); xfDelete.setInt(1, id);
st.executeUpdate(); xfDelete.executeUpdate();
st.close(); }
} }
rs.close();
pst.close();
} }
pst = con.prepareStatement("DELETE FROM " + tableName + " WHERE " + col.NAME + "=?;");
pst.setString(1, user); pst.setString(1, user);
pst.executeUpdate(); pst.executeUpdate();
return true; return true;
} catch (SQLException ex) { } catch (SQLException ex) {
logSqlException(ex); logSqlException(ex);
} finally {
close(xfSelect);
close(xfDelete);
} }
return false; return false;
} }
@ -817,18 +830,6 @@ public class MySQL implements DataSource {
return result; return result;
} }
@Override
public void updateName(String oldOne, String newOne) {
String sql = "UPDATE " + tableName + " SET " + col.NAME + "=? WHERE " + col.NAME + "=?;";
try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
pst.setString(1, newOne);
pst.setString(2, oldOne);
pst.executeUpdate();
} catch (SQLException ex) {
logSqlException(ex);
}
}
@Override @Override
public boolean updateRealName(String user, String realName) { public boolean updateRealName(String user, String realName) {
String sql = "UPDATE " + tableName + " SET " + col.REAL_NAME + "=? WHERE " + col.NAME + "=?;"; String sql = "UPDATE " + tableName + " SET " + col.REAL_NAME + "=? WHERE " + col.NAME + "=?;";
@ -891,22 +892,24 @@ public class MySQL implements DataSource {
@Override @Override
public List<PlayerAuth> getLoggedPlayers() { public List<PlayerAuth> getLoggedPlayers() {
List<PlayerAuth> auths = new ArrayList<>(); List<PlayerAuth> auths = new ArrayList<>();
try (Connection con = getConnection()) { String sql = "SELECT * FROM " + tableName + " WHERE " + col.IS_LOGGED + "=1;";
Statement st = con.createStatement(); try (Connection con = getConnection();
ResultSet rs = st.executeQuery("SELECT * FROM " + tableName + " WHERE " + col.IS_LOGGED + "=1;"); Statement st = con.createStatement();
PreparedStatement pst = con.prepareStatement("SELECT data FROM xf_user_authenticate WHERE " + col.ID + "=?;"); ResultSet rs = st.executeQuery(sql)) {
while (rs.next()) { while (rs.next()) {
PlayerAuth pAuth = buildAuthFromResultSet(rs); PlayerAuth pAuth = buildAuthFromResultSet(rs);
if (hashAlgorithm == HashAlgorithm.XFBCRYPT) { if (hashAlgorithm == HashAlgorithm.XFBCRYPT) {
int id = rs.getInt(col.ID); try (PreparedStatement pst = con.prepareStatement("SELECT data FROM xf_user_authenticate WHERE " + col.ID + "=?;")) {
pst.setInt(1, id); int id = rs.getInt(col.ID);
ResultSet rs2 = pst.executeQuery(); pst.setInt(1, id);
if (rs2.next()) { ResultSet rs2 = pst.executeQuery();
Blob blob = rs2.getBlob("data"); if (rs2.next()) {
byte[] bytes = blob.getBytes(1, (int) blob.length()); Blob blob = rs2.getBlob("data");
pAuth.setPassword(new HashedPassword(XFBCRYPT.getHashFromBlob(bytes))); byte[] bytes = blob.getBytes(1, (int) blob.length());
pAuth.setPassword(new HashedPassword(XFBCRYPT.getHashFromBlob(bytes)));
}
rs2.close();
} }
rs2.close();
} }
auths.add(pAuth); auths.add(pAuth);
} }
@ -990,12 +993,22 @@ public class MySQL implements DataSource {
} }
private static void close(ResultSet rs) { private static void close(ResultSet rs) {
if (rs != null) { try {
try { if (rs != null && !rs.isClosed()) {
rs.close(); rs.close();
} catch (SQLException e) {
ConsoleLogger.logException("Could not close ResultSet", e);
} }
} catch (SQLException e) {
ConsoleLogger.logException("Could not close ResultSet", e);
}
}
private static void close(PreparedStatement pst) {
try {
if (pst != null && !pst.isClosed()) {
pst.close();
}
} catch (SQLException e) {
ConsoleLogger.logException("Could not close PreparedStatement", e);
} }
} }

View File

@ -30,8 +30,9 @@ public class SQLite implements DataSource {
/** /**
* Constructor for SQLite. * Constructor for SQLite.
* *
* @throws ClassNotFoundException Exception * @param settings The settings instance
* @throws SQLException Exception * @throws ClassNotFoundException if no driver could be found for the datasource
* @throws SQLException when initialization of a SQL datasource failed
*/ */
public SQLite(NewSetting settings) throws ClassNotFoundException, SQLException { public SQLite(NewSetting settings) throws ClassNotFoundException, SQLException {
this.database = settings.getProperty(DatabaseSettings.MYSQL_DATABASE); this.database = settings.getProperty(DatabaseSettings.MYSQL_DATABASE);
@ -350,8 +351,9 @@ public class SQLite implements DataSource {
@Override @Override
public synchronized void close() { public synchronized void close() {
try { try {
if (con != null && !con.isClosed()) if (con != null && !con.isClosed()) {
con.close(); con.close();
}
} catch (SQLException ex) { } catch (SQLException ex) {
logSqlException(ex); logSqlException(ex);
} }
@ -421,17 +423,14 @@ public class SQLite implements DataSource {
@Override @Override
public void purgeBanned(List<String> banned) { public void purgeBanned(List<String> banned) {
PreparedStatement pst = null; String sql = "DELETE FROM " + tableName + " WHERE " + col.NAME + "=?;";
try { try (PreparedStatement pst = con.prepareStatement(sql)) {
for (String name : banned) { for (String name : banned) {
pst = con.prepareStatement("DELETE FROM " + tableName + " WHERE " + col.NAME + "=?;");
pst.setString(1, name); pst.setString(1, name);
pst.executeUpdate(); pst.executeUpdate();
} }
} catch (SQLException ex) { } catch (SQLException ex) {
logSqlException(ex); logSqlException(ex);
} finally {
close(pst);
} }
} }
@ -507,37 +506,17 @@ public class SQLite implements DataSource {
@Override @Override
public int getAccountsRegistered() { public int getAccountsRegistered() {
PreparedStatement pst = null; String sql = "SELECT COUNT(*) FROM " + tableName + ";";
ResultSet rs; try (PreparedStatement pst = con.prepareStatement(sql); ResultSet rs = pst.executeQuery()) {
try { if (rs.next()) {
pst = con.prepareStatement("SELECT COUNT(*) FROM " + tableName + ";");
rs = pst.executeQuery();
if (rs != null && rs.next()) {
return rs.getInt(1); return rs.getInt(1);
} }
} catch (SQLException ex) { } catch (SQLException ex) {
logSqlException(ex); logSqlException(ex);
} finally {
close(pst);
} }
return 0; return 0;
} }
@Override
public void updateName(String oldOne, String newOne) {
PreparedStatement pst = null;
try {
pst = con.prepareStatement("UPDATE " + tableName + " SET " + col.NAME + "=? WHERE " + col.NAME + "=?;");
pst.setString(1, newOne);
pst.setString(2, oldOne);
pst.executeUpdate();
} catch (SQLException ex) {
logSqlException(ex);
} finally {
close(pst);
}
}
@Override @Override
public boolean updateRealName(String user, String realName) { public boolean updateRealName(String user, String realName) {
String sql = "UPDATE " + tableName + " SET " + col.REAL_NAME + "=? WHERE " + col.NAME + "=?;"; String sql = "UPDATE " + tableName + " SET " + col.REAL_NAME + "=? WHERE " + col.NAME + "=?;";
@ -569,19 +548,14 @@ public class SQLite implements DataSource {
@Override @Override
public List<PlayerAuth> getAllAuths() { public List<PlayerAuth> getAllAuths() {
List<PlayerAuth> auths = new ArrayList<>(); List<PlayerAuth> auths = new ArrayList<>();
PreparedStatement pst = null; String sql = "SELECT * FROM " + tableName + ";";
ResultSet rs; try (PreparedStatement pst = con.prepareStatement(sql); ResultSet rs = pst.executeQuery()) {
try {
pst = con.prepareStatement("SELECT * FROM " + tableName + ";");
rs = pst.executeQuery();
while (rs.next()) { while (rs.next()) {
PlayerAuth auth = buildAuthFromResultSet(rs); PlayerAuth auth = buildAuthFromResultSet(rs);
auths.add(auth); auths.add(auth);
} }
} catch (SQLException ex) { } catch (SQLException ex) {
logSqlException(ex); logSqlException(ex);
} finally {
close(pst);
} }
return auths; return auths;
} }
@ -589,19 +563,14 @@ public class SQLite implements DataSource {
@Override @Override
public List<PlayerAuth> getLoggedPlayers() { public List<PlayerAuth> getLoggedPlayers() {
List<PlayerAuth> auths = new ArrayList<>(); List<PlayerAuth> auths = new ArrayList<>();
PreparedStatement pst = null; String sql = "SELECT * FROM " + tableName + " WHERE " + col.IS_LOGGED + "=1;";
ResultSet rs; try (PreparedStatement pst = con.prepareStatement(sql); ResultSet rs = pst.executeQuery()) {
try {
pst = con.prepareStatement("SELECT * FROM " + tableName + " WHERE " + col.IS_LOGGED + "=1;");
rs = pst.executeQuery();
while (rs.next()) { while (rs.next()) {
PlayerAuth auth = buildAuthFromResultSet(rs); PlayerAuth auth = buildAuthFromResultSet(rs);
auths.add(auth); auths.add(auth);
} }
} catch (SQLException ex) { } catch (SQLException ex) {
logSqlException(ex); logSqlException(ex);
} finally {
close(pst);
} }
return auths; return auths;
} }

View File

@ -6,7 +6,7 @@ import org.bukkit.event.HandlerList;
/** /**
* This event is called when a player uses the /login command with correct credentials. * This event is called when a player uses the /login command with correct credentials.
* {@link #setCanLogin(boolean) {@code event.setCanLogin(false)}} prevents the player from logging in. * {@link #setCanLogin(boolean) event.setCanLogin(false)} prevents the player from logging in.
*/ */
public class AuthMeAsyncPreLoginEvent extends CustomEvent { public class AuthMeAsyncPreLoginEvent extends CustomEvent {

View File

@ -41,7 +41,7 @@ public enum MessageKey {
REGISTER_EMAIL_MESSAGE("reg_email_msg"), REGISTER_EMAIL_MESSAGE("reg_email_msg"),
MAX_REGISTER_EXCEEDED("max_reg"), MAX_REGISTER_EXCEEDED("max_reg", "%max_acc", "%reg_count", "%reg_names"),
USAGE_REGISTER("usage_reg"), USAGE_REGISTER("usage_reg"),

View File

@ -96,6 +96,7 @@ public class Messages {
* *
* @param key The key of the message to send * @param key The key of the message to send
* @param replacements The replacements to apply for the tags * @param replacements The replacements to apply for the tags
* @return The message from the file with replacements
*/ */
public String retrieveSingle(MessageKey key, String... replacements) { public String retrieveSingle(MessageKey key, String... replacements) {
String message = retrieveSingle(key); String message = retrieveSingle(key);
@ -111,7 +112,7 @@ public class Messages {
} }
/** /**
* Reload the messages manager. * Reset the messages manager to retrieve messages from the given file instead of the current one.
* *
* @param messagesFile The new file to load messages from * @param messagesFile The new file to load messages from
*/ */

View File

@ -2,6 +2,7 @@ package fr.xephi.authme.process;
import fr.xephi.authme.AuthMe; import fr.xephi.authme.AuthMe;
import fr.xephi.authme.cache.auth.PlayerCache; import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.process.email.AsyncAddEmail; import fr.xephi.authme.process.email.AsyncAddEmail;
import fr.xephi.authme.process.email.AsyncChangeEmail; import fr.xephi.authme.process.email.AsyncChangeEmail;
import fr.xephi.authme.process.join.AsynchronousJoin; import fr.xephi.authme.process.join.AsynchronousJoin;
@ -20,18 +21,25 @@ public class Management {
private final AuthMe plugin; private final AuthMe plugin;
private final BukkitScheduler sched; private final BukkitScheduler sched;
private final ProcessService processService;
private final DataSource dataSource;
private final PlayerCache playerCache;
private final NewSetting settings; private final NewSetting settings;
/** /**
* Constructor for Management. * Constructor for Management.
* *
* @param plugin AuthMe * @param plugin AuthMe
* @param settings The plugin settings
*/ */
public Management(AuthMe plugin, NewSetting settings) { public Management(AuthMe plugin, ProcessService processService, DataSource dataSource, PlayerCache playerCache) {
this.plugin = plugin; this.plugin = plugin;
this.sched = this.plugin.getServer().getScheduler(); this.sched = this.plugin.getServer().getScheduler();
this.settings = settings; this.processService = processService;
this.dataSource = dataSource;
this.playerCache = playerCache;
// FIXME don't pass settings anymore -> go through the service in the processes
this.settings = processService.getSettings();
} }
public void performLogin(final Player player, final String password, final boolean forceLogin) { public void performLogin(final Player player, final String password, final boolean forceLogin) {
@ -39,7 +47,7 @@ public class Management {
@Override @Override
public void run() { public void run() {
new AsynchronousLogin(player, password, forceLogin, plugin, plugin.getDataSource(), settings) new AsynchronousLogin(player, password, forceLogin, plugin, dataSource, settings)
.process(); .process();
} }
}); });
@ -60,7 +68,7 @@ public class Management {
@Override @Override
public void run() { public void run() {
new AsyncRegister(player, password, email, plugin, plugin.getDataSource(), settings).process(); new AsyncRegister(player, password, email, plugin, dataSource, settings).process();
} }
}); });
} }
@ -76,14 +84,7 @@ public class Management {
} }
public void performJoin(final Player player) { public void performJoin(final Player player) {
sched.runTaskAsynchronously(plugin, new Runnable() { runTask(new AsynchronousJoin(player, plugin, dataSource, playerCache, processService));
@Override
public void run() {
new AsynchronousJoin(player, plugin, plugin.getDataSource()).process();
}
});
} }
public void performQuit(final Player player, final boolean isKick) { public void performQuit(final Player player, final boolean isKick) {
@ -91,28 +92,26 @@ public class Management {
@Override @Override
public void run() { public void run() {
new AsynchronousQuit(player, plugin, plugin.getDataSource(), isKick).process(); new AsynchronousQuit(player, plugin, dataSource, isKick).process();
} }
}); });
} }
public void performAddEmail(final Player player, final String newEmail) { public void performAddEmail(final Player player, final String newEmail) {
sched.runTaskAsynchronously(plugin, new Runnable() { runTask(new AsyncAddEmail(player, newEmail, dataSource, playerCache, processService));
@Override
public void run() {
new AsyncAddEmail(player, plugin, newEmail, plugin.getDataSource(),
PlayerCache.getInstance(), settings).process();
}
});
} }
public void performChangeEmail(final Player player, final String oldEmail, final String newEmail) { public void performChangeEmail(final Player player, final String oldEmail, final String newEmail) {
sched.runTaskAsynchronously(plugin, new Runnable() { sched.runTaskAsynchronously(plugin, new Runnable() {
@Override @Override
public void run() { public void run() {
new AsyncChangeEmail(player, plugin, oldEmail, newEmail, plugin.getDataSource(), PlayerCache.getInstance(), settings).process(); new AsyncChangeEmail(player, plugin, oldEmail, newEmail, dataSource, playerCache, settings).process();
} }
}); });
} }
private void runTask(Process process) {
sched.runTaskAsynchronously(plugin, process);
}
} }

View File

@ -0,0 +1,8 @@
package fr.xephi.authme.process;
/**
* Common interface for AuthMe processes.
*/
public interface Process extends Runnable {
}

View File

@ -0,0 +1,63 @@
package fr.xephi.authme.process;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.output.Messages;
import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.domain.Property;
import org.bukkit.command.CommandSender;
import org.bukkit.event.Event;
import org.bukkit.scheduler.BukkitTask;
/**
* Service for asynchronous and synchronous processes.
*/
public class ProcessService {
private final NewSetting settings;
private final Messages messages;
private final AuthMe authMe;
public ProcessService(NewSetting settings, Messages messages, AuthMe authMe) {
this.settings = settings;
this.messages = messages;
this.authMe = authMe;
}
public <T> T getProperty(Property<T> property) {
return settings.getProperty(property);
}
public NewSetting getSettings() {
return settings;
}
public void send(CommandSender sender, MessageKey key) {
messages.send(sender, key);
}
public String retrieveMessage(MessageKey key) {
return messages.retrieveSingle(key);
}
public BukkitTask runTask(Runnable task) {
return authMe.getServer().getScheduler().runTask(authMe, task);
}
public BukkitTask runTaskLater(Runnable task, long delay) {
return authMe.getServer().getScheduler().runTaskLater(authMe, task, delay);
}
public int scheduleSyncDelayedTask(Runnable task) {
return authMe.getServer().getScheduler().scheduleSyncDelayedTask(authMe, task);
}
public void callEvent(Event event) {
authMe.getServer().getPluginManager().callEvent(event);
}
public AuthMe getAuthMe() {
return authMe;
}
}

View File

@ -1,40 +1,38 @@
package fr.xephi.authme.process.email; package fr.xephi.authme.process.email;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.cache.auth.PlayerCache; import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.output.Messages; import fr.xephi.authme.process.Process;
import fr.xephi.authme.settings.NewSetting; import fr.xephi.authme.process.ProcessService;
import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.properties.RegistrationSettings;
import fr.xephi.authme.util.Utils; import fr.xephi.authme.util.Utils;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
/** /**
* Async task to add an email to an account. * Async task to add an email to an account.
*/ */
public class AsyncAddEmail { public class AsyncAddEmail implements Process {
private final Player player; private final Player player;
private final String email; private final String email;
private final Messages messages; private final ProcessService service;
private final DataSource dataSource; private final DataSource dataSource;
private final PlayerCache playerCache; private final PlayerCache playerCache;
private final NewSetting settings;
public AsyncAddEmail(Player player, AuthMe plugin, String email, DataSource dataSource, public AsyncAddEmail(Player player, String email, DataSource dataSource, PlayerCache playerCache,
PlayerCache playerCache, NewSetting settings) { ProcessService service) {
this.messages = plugin.getMessages();
this.player = player; this.player = player;
this.email = email; this.email = email;
this.dataSource = dataSource; this.dataSource = dataSource;
this.playerCache = playerCache; this.playerCache = playerCache;
this.settings = settings; this.service = service;
} }
public void process() { @Override
public void run() {
String playerName = player.getName().toLowerCase(); String playerName = player.getName().toLowerCase();
if (playerCache.isAuthenticated(playerName)) { if (playerCache.isAuthenticated(playerName)) {
@ -42,19 +40,19 @@ public class AsyncAddEmail {
final String currentEmail = auth.getEmail(); final String currentEmail = auth.getEmail();
if (currentEmail != null && !"your@email.com".equals(currentEmail)) { if (currentEmail != null && !"your@email.com".equals(currentEmail)) {
messages.send(player, MessageKey.USAGE_CHANGE_EMAIL); service.send(player, MessageKey.USAGE_CHANGE_EMAIL);
} else if (!Utils.isEmailCorrect(email, settings)) { } else if (!Utils.isEmailCorrect(email, service.getSettings())) {
messages.send(player, MessageKey.INVALID_EMAIL); service.send(player, MessageKey.INVALID_EMAIL);
} else if (dataSource.isEmailStored(email)) { } else if (dataSource.isEmailStored(email)) {
messages.send(player, MessageKey.EMAIL_ALREADY_USED_ERROR); service.send(player, MessageKey.EMAIL_ALREADY_USED_ERROR);
} else { } else {
auth.setEmail(email); auth.setEmail(email);
if (dataSource.updateEmail(auth)) { if (dataSource.updateEmail(auth)) {
playerCache.updatePlayer(auth); playerCache.updatePlayer(auth);
messages.send(player, MessageKey.EMAIL_ADDED_SUCCESS); service.send(player, MessageKey.EMAIL_ADDED_SUCCESS);
} else { } else {
ConsoleLogger.showError("Could not save email for player '" + player + "'"); ConsoleLogger.showError("Could not save email for player '" + player + "'");
messages.send(player, MessageKey.ERROR); service.send(player, MessageKey.ERROR);
} }
} }
} else { } else {
@ -64,11 +62,11 @@ public class AsyncAddEmail {
private void sendUnloggedMessage(DataSource dataSource) { private void sendUnloggedMessage(DataSource dataSource) {
if (dataSource.isAuthAvailable(player.getName())) { if (dataSource.isAuthAvailable(player.getName())) {
messages.send(player, MessageKey.LOGIN_MESSAGE); service.send(player, MessageKey.LOGIN_MESSAGE);
} else if (Settings.emailRegistration) { } else if (service.getProperty(RegistrationSettings.USE_EMAIL_REGISTRATION)) {
messages.send(player, MessageKey.REGISTER_EMAIL_MESSAGE); service.send(player, MessageKey.REGISTER_EMAIL_MESSAGE);
} else { } else {
messages.send(player, MessageKey.REGISTER_MESSAGE); service.send(player, MessageKey.REGISTER_MESSAGE);
} }
} }

View File

@ -11,66 +11,71 @@ import fr.xephi.authme.events.ProtectInventoryEvent;
import fr.xephi.authme.events.SpawnTeleportEvent; import fr.xephi.authme.events.SpawnTeleportEvent;
import fr.xephi.authme.listener.AuthMePlayerListener; import fr.xephi.authme.listener.AuthMePlayerListener;
import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.output.Messages;
import fr.xephi.authme.permission.PlayerStatePermission; import fr.xephi.authme.permission.PlayerStatePermission;
import fr.xephi.authme.process.Process;
import fr.xephi.authme.process.ProcessService;
import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.Spawn; import fr.xephi.authme.settings.Spawn;
import fr.xephi.authme.settings.properties.HooksSettings;
import fr.xephi.authme.settings.properties.PluginSettings;
import fr.xephi.authme.settings.properties.RegistrationSettings;
import fr.xephi.authme.settings.properties.RestrictionSettings;
import fr.xephi.authme.task.MessageTask; import fr.xephi.authme.task.MessageTask;
import fr.xephi.authme.task.TimeoutTask; import fr.xephi.authme.task.TimeoutTask;
import fr.xephi.authme.util.Utils; import fr.xephi.authme.util.Utils;
import fr.xephi.authme.util.Utils.GroupType; import fr.xephi.authme.util.Utils.GroupType;
import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType; import org.bukkit.potion.PotionEffectType;
import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.scheduler.BukkitTask; import org.bukkit.scheduler.BukkitTask;
/** /**
*/ */
public class AsynchronousJoin { public class AsynchronousJoin implements Process {
private final AuthMe plugin; private final AuthMe plugin;
private final Player player; private final Player player;
private final DataSource database; private final DataSource database;
private final String name; private final String name;
private final Messages m; private final ProcessService service;
private final BukkitScheduler sched; private final PlayerCache playerCache;
public AsynchronousJoin(Player player, AuthMe plugin, DataSource database) { public AsynchronousJoin(Player player, AuthMe plugin, DataSource database, PlayerCache playerCache,
this.m = plugin.getMessages(); ProcessService service) {
this.player = player; this.player = player;
this.plugin = plugin; this.plugin = plugin;
this.sched = plugin.getServer().getScheduler();
this.database = database; this.database = database;
this.name = player.getName().toLowerCase(); this.name = player.getName().toLowerCase();
this.service = service;
this.playerCache = playerCache;
} }
public void process() { @Override
public void run() {
if (Utils.isUnrestricted(player)) { if (Utils.isUnrestricted(player)) {
return; return;
} }
if (Settings.checkVeryGames) { if (service.getProperty(HooksSettings.ENABLE_VERYGAMES_IP_CHECK)) {
plugin.getVerygamesIp(player); plugin.getVerygamesIp(player);
} }
if (plugin.ess != null && Settings.disableSocialSpy) { if (plugin.ess != null && service.getProperty(HooksSettings.DISABLE_SOCIAL_SPY)) {
plugin.ess.getUser(player).setSocialSpyEnabled(false); plugin.ess.getUser(player).setSocialSpyEnabled(false);
} }
final String ip = plugin.getIP(player); final String ip = plugin.getIP(player);
if (Settings.isAllowRestrictedIp && isNameRestricted(name, ip, player.getAddress().getHostName())) { if (isNameRestricted(name, ip, player.getAddress().getHostName(), service.getSettings())) {
sched.scheduleSyncDelayedTask(plugin, new Runnable() { service.scheduleSyncDelayedTask(new Runnable() {
@Override @Override
public void run() { public void run() {
AuthMePlayerListener.causeByAuthMe.putIfAbsent(name, true); AuthMePlayerListener.causeByAuthMe.putIfAbsent(name, true);
player.kickPlayer(m.retrieveSingle(MessageKey.NOT_OWNER_ERROR)); player.kickPlayer(service.retrieveMessage(MessageKey.NOT_OWNER_ERROR));
if (Settings.banUnsafeIp) { if (Settings.banUnsafeIp) {
plugin.getServer().banIP(ip); plugin.getServer().banIP(ip);
} }
@ -78,38 +83,34 @@ public class AsynchronousJoin {
}); });
return; return;
} }
if (Settings.getMaxJoinPerIp > 0 if (service.getProperty(RestrictionSettings.MAX_JOIN_PER_IP) > 0
&& !plugin.getPermissionsManager().hasPermission(player, PlayerStatePermission.ALLOW_MULTIPLE_ACCOUNTS) && !plugin.getPermissionsManager().hasPermission(player, PlayerStatePermission.ALLOW_MULTIPLE_ACCOUNTS)
&& !ip.equalsIgnoreCase("127.0.0.1") && !"127.0.0.1".equalsIgnoreCase(ip)
&& !ip.equalsIgnoreCase("localhost") && !"localhost".equalsIgnoreCase(ip)
&& plugin.hasJoinedIp(player.getName(), ip)) { && hasJoinedIp(player.getName(), ip, service.getSettings(), service.getAuthMe())) {
sched.scheduleSyncDelayedTask(plugin, new Runnable() { service.scheduleSyncDelayedTask(new Runnable() {
@Override @Override
public void run() { public void run() {
player.kickPlayer("A player with the same IP is already in game!"); player.kickPlayer("A player with the same IP is already in game!");
} }
}); });
return; return;
} }
final Location spawnLoc = plugin.getSpawnLocation(player); final Location spawnLoc = Spawn.getInstance().getSpawnLocation(player);
final boolean isAuthAvailable = database.isAuthAvailable(name); final boolean isAuthAvailable = database.isAuthAvailable(name);
if (isAuthAvailable) { if (isAuthAvailable) {
if (!Settings.noTeleport) { if (!Settings.noTeleport) {
if (Settings.isTeleportToSpawnEnabled || (Settings.isForceSpawnLocOnJoinEnabled && Settings.getForcedWorlds.contains(player.getWorld().getName()))) { if (Settings.isTeleportToSpawnEnabled || (Settings.isForceSpawnLocOnJoinEnabled && Settings.getForcedWorlds.contains(player.getWorld().getName()))) {
sched.scheduleSyncDelayedTask(plugin, new Runnable() { service.scheduleSyncDelayedTask(new Runnable() {
@Override @Override
public void run() { public void run() {
SpawnTeleportEvent tpEvent = new SpawnTeleportEvent(player, player.getLocation(), spawnLoc, PlayerCache.getInstance().isAuthenticated(name)); SpawnTeleportEvent tpEvent = new SpawnTeleportEvent(player, player.getLocation(), spawnLoc, playerCache.isAuthenticated(name));
plugin.getServer().getPluginManager().callEvent(tpEvent); service.callEvent(tpEvent);
if (!tpEvent.isCancelled() && player.isOnline() && tpEvent.getTo() != null if (!tpEvent.isCancelled() && player.isOnline() && tpEvent.getTo() != null
&& tpEvent.getTo().getWorld() != null) { && tpEvent.getTo().getWorld() != null) {
player.teleport(tpEvent.getTo()); player.teleport(tpEvent.getTo());
} }
} }
}); });
} }
} }
@ -123,12 +124,12 @@ public class AsynchronousJoin {
if (ev.isCancelled()) { if (ev.isCancelled()) {
plugin.inventoryProtector.sendInventoryPacket(player); plugin.inventoryProtector.sendInventoryPacket(player);
if (!Settings.noConsoleSpam) { if (!Settings.noConsoleSpam) {
ConsoleLogger.info("ProtectInventoryEvent has been cancelled for " + player.getName() + " ..."); ConsoleLogger.info("ProtectInventoryEvent has been cancelled for " + player.getName() + "...");
} }
} }
} }
if (Settings.isSessionsEnabled && (PlayerCache.getInstance().isAuthenticated(name) || database.isLogged(name))) { if (service.getProperty(PluginSettings.SESSIONS_ENABLED) && (playerCache.isAuthenticated(name) || database.isLogged(name))) {
if (plugin.sessions.containsKey(name)) { if (plugin.sessions.containsKey(name)) {
plugin.sessions.get(name).cancel(); plugin.sessions.get(name).cancel();
plugin.sessions.remove(name); plugin.sessions.remove(name);
@ -137,11 +138,11 @@ public class AsynchronousJoin {
database.setUnlogged(name); database.setUnlogged(name);
PlayerCache.getInstance().removePlayer(name); PlayerCache.getInstance().removePlayer(name);
if (auth != null && auth.getIp().equals(ip)) { if (auth != null && auth.getIp().equals(ip)) {
m.send(player, MessageKey.SESSION_RECONNECTION); service.send(player, MessageKey.SESSION_RECONNECTION);
plugin.getManagement().performLogin(player, "dontneed", true); plugin.getManagement().performLogin(player, "dontneed", true);
return; return;
} else if (Settings.sessionExpireOnIpChange) { } else if (Settings.sessionExpireOnIpChange) {
m.send(player, MessageKey.SESSION_EXPIRED); service.send(player, MessageKey.SESSION_EXPIRED);
} }
} }
} else { } else {
@ -154,21 +155,18 @@ public class AsynchronousJoin {
if (!Settings.noTeleport && !needFirstSpawn() && Settings.isTeleportToSpawnEnabled if (!Settings.noTeleport && !needFirstSpawn() && Settings.isTeleportToSpawnEnabled
|| (Settings.isForceSpawnLocOnJoinEnabled && Settings.getForcedWorlds.contains(player.getWorld().getName()))) { || (Settings.isForceSpawnLocOnJoinEnabled && Settings.getForcedWorlds.contains(player.getWorld().getName()))) {
sched.scheduleSyncDelayedTask(plugin, new Runnable() { service.scheduleSyncDelayedTask(new Runnable() {
@Override @Override
public void run() { public void run() {
SpawnTeleportEvent tpEvent = new SpawnTeleportEvent(player, player.getLocation(), spawnLoc, PlayerCache.getInstance().isAuthenticated(name)); SpawnTeleportEvent tpEvent = new SpawnTeleportEvent(player, player.getLocation(), spawnLoc, PlayerCache.getInstance().isAuthenticated(name));
plugin.getServer().getPluginManager().callEvent(tpEvent); service.callEvent(tpEvent);
if (!tpEvent.isCancelled() && player.isOnline() && tpEvent.getTo() != null if (!tpEvent.isCancelled() && player.isOnline() && tpEvent.getTo() != null
&& tpEvent.getTo().getWorld() != null) { && tpEvent.getTo().getWorld() != null) {
player.teleport(tpEvent.getTo()); player.teleport(tpEvent.getTo());
}
} }
}
}); });
} }
} }
if (!LimboCache.getInstance().hasLimboPlayer(name)) { if (!LimboCache.getInstance().hasLimboPlayer(name)) {
@ -176,9 +174,9 @@ public class AsynchronousJoin {
} }
Utils.setGroup(player, isAuthAvailable ? GroupType.NOTLOGGEDIN : GroupType.UNREGISTERED); Utils.setGroup(player, isAuthAvailable ? GroupType.NOTLOGGEDIN : GroupType.UNREGISTERED);
final int timeOut = Settings.getRegistrationTimeout * 20; final int registrationTimeout = service.getProperty(RestrictionSettings.TIMEOUT) * 20;
sched.scheduleSyncDelayedTask(plugin, new Runnable() { service.scheduleSyncDelayedTask(new Runnable() {
@Override @Override
public void run() { public void run() {
player.setOp(false); player.setOp(false);
@ -186,40 +184,35 @@ public class AsynchronousJoin {
player.setFlySpeed(0.0f); player.setFlySpeed(0.0f);
player.setWalkSpeed(0.0f); player.setWalkSpeed(0.0f);
} }
player.setNoDamageTicks(timeOut); player.setNoDamageTicks(registrationTimeout);
if (Settings.useEssentialsMotd) { if (service.getProperty(HooksSettings.USE_ESSENTIALS_MOTD)) {
player.performCommand("motd"); player.performCommand("motd");
} }
if (Settings.applyBlindEffect) { if (service.getProperty(RegistrationSettings.APPLY_BLIND_EFFECT)) {
int blindTimeOut;
// Allow infinite blindness effect // Allow infinite blindness effect
if (timeOut <= 0) { int blindTimeOut = (registrationTimeout <= 0) ? 99999 : registrationTimeout;
blindTimeOut = 99999;
} else {
blindTimeOut = timeOut;
}
player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, blindTimeOut, 2)); player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, blindTimeOut, 2));
} }
} }
}); });
int msgInterval = Settings.getWarnMessageInterval; int msgInterval = service.getProperty(RegistrationSettings.MESSAGE_INTERVAL);
if (timeOut > 0) { if (registrationTimeout > 0) {
BukkitTask id = sched.runTaskLaterAsynchronously(plugin, new TimeoutTask(plugin, name, player), timeOut); BukkitTask id = service.runTaskLater(new TimeoutTask(plugin, name, player), registrationTimeout);
LimboCache.getInstance().getLimboPlayer(name).setTimeoutTaskId(id); LimboCache.getInstance().getLimboPlayer(name).setTimeoutTaskId(id);
} }
String[] msg; MessageKey msg;
if (isAuthAvailable) { if (isAuthAvailable) {
msg = m.retrieve(MessageKey.LOGIN_MESSAGE); msg = MessageKey.LOGIN_MESSAGE;
} else { } else {
msg = Settings.emailRegistration msg = Settings.emailRegistration
? m.retrieve(MessageKey.REGISTER_EMAIL_MESSAGE) ? MessageKey.REGISTER_EMAIL_MESSAGE
: m.retrieve(MessageKey.REGISTER_MESSAGE); : MessageKey.REGISTER_MESSAGE;
} }
if (msgInterval > 0 && LimboCache.getInstance().getLimboPlayer(name) != null) { if (msgInterval > 0 && LimboCache.getInstance().getLimboPlayer(name) != null) {
BukkitTask msgTask = sched.runTaskAsynchronously(plugin, new MessageTask(plugin, name, msg, msgInterval)); BukkitTask msgTask = service.runTask(new MessageTask(plugin, name, msg, msgInterval));
LimboCache.getInstance().getLimboPlayer(name).setMessageTaskId(msgTask); LimboCache.getInstance().getLimboPlayer(name).setMessageTaskId(msgTask);
} }
} }
@ -235,13 +228,11 @@ public class AsynchronousJoin {
if (!tpEvent.isCancelled()) { if (!tpEvent.isCancelled()) {
if (player.isOnline() && tpEvent.getTo() != null && tpEvent.getTo().getWorld() != null) { if (player.isOnline() && tpEvent.getTo() != null && tpEvent.getTo().getWorld() != null) {
final Location fLoc = tpEvent.getTo(); final Location fLoc = tpEvent.getTo();
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { service.scheduleSyncDelayedTask(new Runnable() {
@Override @Override
public void run() { public void run() {
player.teleport(fLoc); player.teleport(fLoc);
} }
}); });
} }
} }
@ -249,25 +240,23 @@ public class AsynchronousJoin {
} }
private void placePlayerSafely(final Player player, final Location spawnLoc) { private void placePlayerSafely(final Player player, final Location spawnLoc) {
if (spawnLoc == null) if (spawnLoc == null || service.getProperty(RestrictionSettings.NO_TELEPORT))
return;
if (!Settings.noTeleport)
return; return;
if (Settings.isTeleportToSpawnEnabled || (Settings.isForceSpawnLocOnJoinEnabled && Settings.getForcedWorlds.contains(player.getWorld().getName()))) if (Settings.isTeleportToSpawnEnabled || (Settings.isForceSpawnLocOnJoinEnabled && Settings.getForcedWorlds.contains(player.getWorld().getName())))
return; return;
if (!player.hasPlayedBefore()) if (!player.hasPlayedBefore())
return; return;
sched.scheduleSyncDelayedTask(plugin, new Runnable() { service.scheduleSyncDelayedTask(new Runnable() {
@Override @Override
public void run() { public void run() {
if (spawnLoc.getWorld() == null) { if (spawnLoc.getWorld() == null) {
return; return;
} }
Material cur = player.getLocation().getBlock().getType(); Material cur = player.getLocation().getBlock().getType();
Material top = player.getLocation().add(0D, 1D, 0D).getBlock().getType(); Material top = player.getLocation().add(0, 1, 0).getBlock().getType();
if (cur == Material.PORTAL || cur == Material.ENDER_PORTAL if (cur == Material.PORTAL || cur == Material.ENDER_PORTAL
|| top == Material.PORTAL || top == Material.ENDER_PORTAL) { || top == Material.PORTAL || top == Material.ENDER_PORTAL) {
m.send(player, MessageKey.UNSAFE_QUIT_LOCATION); service.send(player, MessageKey.UNSAFE_QUIT_LOCATION);
player.teleport(spawnLoc); player.teleport(spawnLoc);
} }
} }
@ -281,12 +270,17 @@ public class AsynchronousJoin {
* @param name The name to check * @param name The name to check
* @param ip The IP address of the player * @param ip The IP address of the player
* @param domain The hostname of the IP address * @param domain The hostname of the IP address
* @param settings The settings instance
* @return True if the name is restricted (IP/domain is not allowed for the given name), * @return True if the name is restricted (IP/domain is not allowed for the given name),
* false if the restrictions are met or if the name has no restrictions to it * false if the restrictions are met or if the name has no restrictions to it
*/ */
private static boolean isNameRestricted(String name, String ip, String domain) { private static boolean isNameRestricted(String name, String ip, String domain, NewSetting settings) {
if (!settings.getProperty(RestrictionSettings.ENABLE_RESTRICTED_USERS)) {
return false;
}
boolean nameFound = false; boolean nameFound = false;
for (String entry : Settings.getRestrictedIp) { for (String entry : settings.getProperty(RestrictionSettings.ALLOWED_RESTRICTED_USERS)) {
String[] args = entry.split(";"); String[] args = entry.split(";");
String testName = args[0]; String testName = args[0];
String testIp = args[1]; String testIp = args[1];
@ -301,4 +295,12 @@ public class AsynchronousJoin {
return nameFound; return nameFound;
} }
private boolean hasJoinedIp(String name, String ip, NewSetting settings, AuthMe authMe) {
int count = 0;
for (Player player : Utils.getOnlinePlayers()) {
if (ip.equalsIgnoreCase(authMe.getIP(player)) && !player.getName().equalsIgnoreCase(name))
count++;
}
return count >= settings.getProperty(RestrictionSettings.MAX_JOIN_PER_IP);
}
} }

View File

@ -105,7 +105,7 @@ public class AsynchronousLogin {
} else { } else {
msg = m.retrieve(MessageKey.REGISTER_MESSAGE); msg = m.retrieve(MessageKey.REGISTER_MESSAGE);
} }
BukkitTask msgT = Bukkit.getScheduler().runTaskAsynchronously(plugin, BukkitTask msgT = Bukkit.getScheduler().runTask(plugin,
new MessageTask(plugin, name, msg, settings.getProperty(RegistrationSettings.MESSAGE_INTERVAL))); new MessageTask(plugin, name, msg, settings.getProperty(RegistrationSettings.MESSAGE_INTERVAL)));
LimboCache.getInstance().getLimboPlayer(name).setMessageTaskId(msgT); LimboCache.getInstance().getLimboPlayer(name).setMessageTaskId(msgT);
} }
@ -175,7 +175,7 @@ public class AsynchronousLogin {
displayOtherAccounts(auth); displayOtherAccounts(auth);
if (Settings.recallEmail && (StringUtils.isEmpty(email) || "your@email.com".equalsIgnoreCase(email))) { if (Settings.recallEmail && (StringUtils.isEmpty(email) || "your@email.com".equalsIgnoreCase(email))) {
m.send(player, MessageKey.EMAIL_ADDED_SUCCESS); m.send(player, MessageKey.ADD_EMAIL_MESSAGE);
} }
if (!Settings.noConsoleSpam) { if (!Settings.noConsoleSpam) {
@ -185,7 +185,6 @@ public class AsynchronousLogin {
// makes player isLoggedin via API // makes player isLoggedin via API
PlayerCache.getInstance().addPlayer(auth); PlayerCache.getInstance().addPlayer(auth);
database.setLogged(name); database.setLogged(name);
plugin.otherAccounts.addPlayer(player.getUniqueId());
// As the scheduling executes the Task most likely after the current // As the scheduling executes the Task most likely after the current
// task, we schedule it in the end // task, we schedule it in the end
@ -232,8 +231,8 @@ public class AsynchronousLogin {
String message = "[AuthMe] " + StringUtils.join(", ", auths) + "."; String message = "[AuthMe] " + StringUtils.join(", ", auths) + ".";
for (Player player : Utils.getOnlinePlayers()) { for (Player player : Utils.getOnlinePlayers()) {
if (plugin.getPermissionsManager().hasPermission(player, AdminPermission.SEE_OTHER_ACCOUNTS) if (plugin.getPermissionsManager().hasPermission(player, AdminPermission.SEE_OTHER_ACCOUNTS)
|| (player.getName().equals(this.player.getName()) || (player.getName().equals(this.player.getName())
&& plugin.getPermissionsManager().hasPermission(player, PlayerPermission.SEE_OWN_ACCOUNTS))) { && plugin.getPermissionsManager().hasPermission(player, PlayerPermission.SEE_OWN_ACCOUNTS))) {
player.sendMessage("[AuthMe] The player " + auth.getNickname() + " has " + auths.size() + " accounts"); player.sendMessage("[AuthMe] The player " + auth.getNickname() + " has " + auths.size() + " accounts");
player.sendMessage(message); player.sendMessage(message);
} }

View File

@ -38,7 +38,6 @@ public class ProcessSyncPlayerLogin implements Runnable {
private final String name; private final String name;
private final PlayerAuth auth; private final PlayerAuth auth;
private final AuthMe plugin; private final AuthMe plugin;
private final DataSource database;
private final PluginManager pm; private final PluginManager pm;
private final JsonCache playerCache; private final JsonCache playerCache;
private final NewSetting settings; private final NewSetting settings;
@ -54,7 +53,6 @@ public class ProcessSyncPlayerLogin implements Runnable {
public ProcessSyncPlayerLogin(Player player, AuthMe plugin, public ProcessSyncPlayerLogin(Player player, AuthMe plugin,
DataSource database, NewSetting settings) { DataSource database, NewSetting settings) {
this.plugin = plugin; this.plugin = plugin;
this.database = database;
this.pm = plugin.getServer().getPluginManager(); this.pm = plugin.getServer().getPluginManager();
this.player = player; this.player = player;
this.name = player.getName().toLowerCase(); this.name = player.getName().toLowerCase();

View File

@ -74,21 +74,24 @@ public class ProcessSyncronousPlayerLogout implements Runnable {
int interval = Settings.getWarnMessageInterval; int interval = Settings.getWarnMessageInterval;
BukkitScheduler sched = player.getServer().getScheduler(); BukkitScheduler sched = player.getServer().getScheduler();
if (timeOut != 0) { if (timeOut != 0) {
BukkitTask id = sched.runTaskLaterAsynchronously(plugin, new TimeoutTask(plugin, name, player), timeOut); BukkitTask id = sched.runTaskLater(plugin, new TimeoutTask(plugin, name, player), timeOut);
LimboCache.getInstance().getLimboPlayer(name).setTimeoutTaskId(id); LimboCache.getInstance().getLimboPlayer(name).setTimeoutTaskId(id);
} }
BukkitTask msgT = sched.runTaskAsynchronously(plugin, new MessageTask(plugin, name, m.retrieve(MessageKey.LOGIN_MESSAGE), interval)); BukkitTask msgT = sched.runTask(plugin, new MessageTask(plugin, name, MessageKey.LOGIN_MESSAGE, interval));
LimboCache.getInstance().getLimboPlayer(name).setMessageTaskId(msgT); LimboCache.getInstance().getLimboPlayer(name).setMessageTaskId(msgT);
if (player.isInsideVehicle() && player.getVehicle() != null) if (player.isInsideVehicle() && player.getVehicle() != null) {
player.getVehicle().eject(); player.getVehicle().eject();
if (Settings.applyBlindEffect) }
player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, Settings.getRegistrationTimeout * 20, 2)); if (Settings.applyBlindEffect) {
player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, timeOut, 2));
}
player.setOp(false); player.setOp(false);
restoreSpeedEffect(); restoreSpeedEffect();
// Player is now logout... Time to fire event ! // Player is now logout... Time to fire event !
Bukkit.getServer().getPluginManager().callEvent(new LogoutEvent(player)); Bukkit.getServer().getPluginManager().callEvent(new LogoutEvent(player));
if (Settings.bungee) if (Settings.bungee) {
sendBungeeMessage(); sendBungeeMessage();
}
m.send(player, MessageKey.LOGOUT_SUCCESS); m.send(player, MessageKey.LOGOUT_SUCCESS);
ConsoleLogger.info(player.getName() + " logged out"); ConsoleLogger.info(player.getName() + " logged out");
} }

View File

@ -5,34 +5,26 @@ import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.cache.auth.PlayerCache; import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.cache.limbo.LimboCache; import fr.xephi.authme.cache.limbo.LimboCache;
import fr.xephi.authme.cache.limbo.LimboPlayer; import fr.xephi.authme.cache.limbo.LimboPlayer;
import fr.xephi.authme.datasource.CacheDataSource;
import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.util.StringUtils;
import fr.xephi.authme.util.Utils; import fr.xephi.authme.util.Utils;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitTask; import org.bukkit.scheduler.BukkitTask;
/**
*/
public class AsynchronousQuit { public class AsynchronousQuit {
protected final AuthMe plugin; private final AuthMe plugin;
protected final DataSource database; private final DataSource database;
protected final Player player; private final Player player;
private final String name; private final String name;
private boolean isOp = false; private boolean isOp = false;
private boolean needToChange = false; private boolean needToChange = false;
private boolean isKick = false; private boolean isKick = false;
/**
* Constructor for AsynchronousQuit.
*
* @param p Player
* @param plugin AuthMe
* @param database DataSource
* @param isKick boolean
*/
public AsynchronousQuit(Player p, AuthMe plugin, DataSource database, public AsynchronousQuit(Player p, AuthMe plugin, DataSource database,
boolean isKick) { boolean isKick) {
this.player = p; this.player = p;
@ -43,9 +35,7 @@ public class AsynchronousQuit {
} }
public void process() { public void process() {
if (player == null) if (player == null || Utils.isUnrestricted(player)) {
return;
if (Utils.isUnrestricted(player)) {
return; return;
} }
@ -54,7 +44,9 @@ public class AsynchronousQuit {
if (PlayerCache.getInstance().isAuthenticated(name)) { if (PlayerCache.getInstance().isAuthenticated(name)) {
if (Settings.isSaveQuitLocationEnabled) { if (Settings.isSaveQuitLocationEnabled) {
Location loc = player.getLocation(); Location loc = player.getLocation();
PlayerAuth auth = new PlayerAuth(name, loc.getX(), loc.getY(), loc.getZ(), loc.getWorld().getName(), player.getName()); PlayerAuth auth = PlayerAuth.builder()
.name(name).location(loc)
.realName(player.getName()).build();
database.updateQuitLoc(auth); database.updateQuitLoc(auth);
} }
PlayerAuth auth = new PlayerAuth(name, ip, System.currentTimeMillis(), player.getName()); PlayerAuth auth = new PlayerAuth(name, ip, System.currentTimeMillis(), player.getName());
@ -63,14 +55,11 @@ public class AsynchronousQuit {
LimboPlayer limbo = LimboCache.getInstance().getLimboPlayer(name); LimboPlayer limbo = LimboCache.getInstance().getLimboPlayer(name);
if (limbo != null) { if (limbo != null) {
if (limbo.getGroup() != null && !limbo.getGroup().isEmpty()) if (!StringUtils.isEmpty(limbo.getGroup())) {
Utils.addNormal(player, limbo.getGroup()); Utils.addNormal(player, limbo.getGroup());
}
needToChange = true; needToChange = true;
isOp = limbo.getOperator(); isOp = limbo.getOperator();
if (limbo.getTimeoutTaskId() != null)
limbo.getTimeoutTaskId().cancel();
if (limbo.getMessageTaskId() != null)
limbo.getMessageTaskId().cancel();
LimboCache.getInstance().deleteLimboPlayer(name); LimboCache.getInstance().deleteLimboPlayer(name);
} }
if (Settings.isSessionsEnabled && !isKick) { if (Settings.isSessionsEnabled && !isKick) {
@ -100,12 +89,15 @@ public class AsynchronousQuit {
if (plugin.isEnabled()) { if (plugin.isEnabled()) {
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new ProcessSyncronousPlayerQuit(plugin, player, isOp, needToChange)); Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new ProcessSyncronousPlayerQuit(plugin, player, isOp, needToChange));
} }
// remove player from cache
if (database instanceof CacheDataSource) {
((CacheDataSource) database).getCachedAuths().invalidate(name);
}
} }
private void postLogout() { private void postLogout() {
PlayerCache.getInstance().removePlayer(name); PlayerCache.getInstance().removePlayer(name);
if (database.isLogged(name)) database.setUnlogged(name);
database.setUnlogged(name);
plugin.sessions.remove(name); plugin.sessions.remove(name);
} }
} }

View File

@ -1,5 +1,10 @@
package fr.xephi.authme.process.register; package fr.xephi.authme.process.register;
import java.util.List;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import fr.xephi.authme.AuthMe; import fr.xephi.authme.AuthMe;
import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.cache.auth.PlayerCache; import fr.xephi.authme.cache.auth.PlayerCache;
@ -13,8 +18,6 @@ import fr.xephi.authme.security.crypts.TwoFactor;
import fr.xephi.authme.settings.NewSetting; import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.util.StringUtils; import fr.xephi.authme.util.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
/** /**
*/ */
@ -74,13 +77,16 @@ public class AsyncRegister {
if (database.isAuthAvailable(name)) { if (database.isAuthAvailable(name)) {
m.send(player, MessageKey.NAME_ALREADY_REGISTERED); m.send(player, MessageKey.NAME_ALREADY_REGISTERED);
return false; return false;
} else if (Settings.getmaxRegPerIp > 0 } else if(Settings.getmaxRegPerIp > 0
&& !plugin.getPermissionsManager().hasPermission(player, PlayerStatePermission.ALLOW_MULTIPLE_ACCOUNTS)
&& !ip.equalsIgnoreCase("127.0.0.1") && !ip.equalsIgnoreCase("127.0.0.1")
&& !ip.equalsIgnoreCase("localhost") && !ip.equalsIgnoreCase("localhost")
&& database.getAllAuthsByIp(ip).size() >= Settings.getmaxRegPerIp) { && !plugin.getPermissionsManager().hasPermission(player, PlayerStatePermission.ALLOW_MULTIPLE_ACCOUNTS)) {
m.send(player, MessageKey.MAX_REGISTER_EXCEEDED); Integer maxReg = Settings.getmaxRegPerIp;
return false; List<String> otherAccounts = database.getAllAuthsByIp(ip);
if (otherAccounts.size() >= maxReg) {
m.send(player, MessageKey.MAX_REGISTER_EXCEEDED, maxReg.toString(), Integer.toString(otherAccounts.size()), otherAccounts.toString());
return false;
}
} }
return true; return true;
} }
@ -96,11 +102,16 @@ public class AsyncRegister {
} }
private void emailRegister() { private void emailRegister() {
if (Settings.getmaxRegPerEmail > 0 if(Settings.getmaxRegPerEmail > 0
&& !plugin.getPermissionsManager().hasPermission(player, PlayerStatePermission.ALLOW_MULTIPLE_ACCOUNTS) && !ip.equalsIgnoreCase("127.0.0.1")
&& database.countAuthsByEmail(email) >= Settings.getmaxRegPerEmail) { && !ip.equalsIgnoreCase("localhost")
m.send(player, MessageKey.MAX_REGISTER_EXCEEDED); && !plugin.getPermissionsManager().hasPermission(player, PlayerStatePermission.ALLOW_MULTIPLE_ACCOUNTS)) {
return; Integer maxReg = Settings.getmaxRegPerIp;
List<String> otherAccounts = database.getAllAuthsByIp(ip);
if (otherAccounts.size() >= maxReg) {
m.send(player, MessageKey.MAX_REGISTER_EXCEEDED, maxReg.toString(), Integer.toString(otherAccounts.size()), otherAccounts.toString());
return;
}
} }
final HashedPassword hashedPassword = plugin.getPasswordSecurity().computeHash(password, name); final HashedPassword hashedPassword = plugin.getPasswordSecurity().computeHash(password, name);
PlayerAuth auth = PlayerAuth.builder() PlayerAuth auth = PlayerAuth.builder()
@ -146,7 +157,6 @@ public class AsyncRegister {
plugin.getManagement().performLogin(player, "dontneed", true); plugin.getManagement().performLogin(player, "dontneed", true);
} }
plugin.otherAccounts.addPlayer(player.getUniqueId());
ProcessSyncPasswordRegister sync = new ProcessSyncPasswordRegister(player, plugin, settings); ProcessSyncPasswordRegister sync = new ProcessSyncPasswordRegister(player, plugin, settings);
plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, sync); plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, sync);

View File

@ -52,14 +52,13 @@ public class ProcessSyncEmailRegister implements Runnable {
int msgInterval = Settings.getWarnMessageInterval; int msgInterval = Settings.getWarnMessageInterval;
BukkitScheduler sched = plugin.getServer().getScheduler(); BukkitScheduler sched = plugin.getServer().getScheduler();
if (time != 0 && limbo != null) {
limbo.getTimeoutTaskId().cancel();
BukkitTask id = sched.runTaskLaterAsynchronously(plugin, new TimeoutTask(plugin, name, player), time);
limbo.setTimeoutTaskId(id);
}
if (limbo != null) { if (limbo != null) {
limbo.getMessageTaskId().cancel(); if (time != 0) {
BukkitTask nwMsg = sched.runTaskAsynchronously(plugin, new MessageTask(plugin, name, m.retrieve(MessageKey.LOGIN_MESSAGE), msgInterval)); BukkitTask id = sched.runTaskLater(plugin, new TimeoutTask(plugin, name, player), time);
limbo.setTimeoutTaskId(id);
}
BukkitTask nwMsg = sched.runTask(plugin, new MessageTask(plugin, name, m.retrieve(MessageKey.LOGIN_MESSAGE), msgInterval));
limbo.setMessageTaskId(nwMsg); limbo.setMessageTaskId(nwMsg);
} }

View File

@ -1,16 +1,7 @@
package fr.xephi.authme.process.register; package fr.xephi.authme.process.register;
import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.properties.HooksSettings;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.scheduler.BukkitTask;
import com.google.common.io.ByteArrayDataOutput; import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams; import com.google.common.io.ByteStreams;
import fr.xephi.authme.AuthMe; import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.limbo.LimboCache; import fr.xephi.authme.cache.limbo.LimboCache;
@ -19,10 +10,17 @@ import fr.xephi.authme.events.LoginEvent;
import fr.xephi.authme.events.RestoreInventoryEvent; import fr.xephi.authme.events.RestoreInventoryEvent;
import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.output.Messages; import fr.xephi.authme.output.Messages;
import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.properties.HooksSettings;
import fr.xephi.authme.task.MessageTask; import fr.xephi.authme.task.MessageTask;
import fr.xephi.authme.task.TimeoutTask; import fr.xephi.authme.task.TimeoutTask;
import fr.xephi.authme.util.Utils; import fr.xephi.authme.util.Utils;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.scheduler.BukkitTask;
/** /**
*/ */
@ -37,8 +35,8 @@ public class ProcessSyncPasswordRegister implements Runnable {
/** /**
* Constructor for ProcessSyncPasswordRegister. * Constructor for ProcessSyncPasswordRegister.
* *
* @param player Player * @param player Player
* @param plugin AuthMe * @param plugin AuthMe
* @param settings The plugin settings * @param settings The plugin settings
*/ */
public ProcessSyncPasswordRegister(Player player, AuthMe plugin, NewSetting settings) { public ProcessSyncPasswordRegister(Player player, AuthMe plugin, NewSetting settings) {
@ -77,11 +75,10 @@ public class ProcessSyncPasswordRegister implements Runnable {
BukkitScheduler sched = plugin.getServer().getScheduler(); BukkitScheduler sched = plugin.getServer().getScheduler();
BukkitTask task; BukkitTask task;
if (delay != 0) { if (delay != 0) {
task = sched.runTaskLaterAsynchronously(plugin, new TimeoutTask(plugin, name, player), delay); task = sched.runTaskLater(plugin, new TimeoutTask(plugin, name, player), delay);
cache.getLimboPlayer(name).setTimeoutTaskId(task); cache.getLimboPlayer(name).setTimeoutTaskId(task);
} }
task = sched.runTaskAsynchronously(plugin, new MessageTask(plugin, name, task = sched.runTask(plugin, new MessageTask(plugin, name, MessageKey.LOGIN_MESSAGE, interval));
m.retrieve(MessageKey.LOGIN_MESSAGE), interval));
cache.getLimboPlayer(name).setMessageTaskId(task); cache.getLimboPlayer(name).setMessageTaskId(task);
if (player.isInsideVehicle() && player.getVehicle() != null) { if (player.isInsideVehicle() && player.getVehicle() != null) {
player.getVehicle().eject(); player.getVehicle().eject();
@ -158,7 +155,7 @@ public class ProcessSyncPasswordRegister implements Runnable {
// Register is now finished; we can force all commands // Register is now finished; we can force all commands
forceCommands(); forceCommands();
sendTo(); sendTo();
} }

View File

@ -73,12 +73,11 @@ public class AsynchronousUnregister {
int interval = Settings.getWarnMessageInterval; int interval = Settings.getWarnMessageInterval;
BukkitScheduler scheduler = plugin.getServer().getScheduler(); BukkitScheduler scheduler = plugin.getServer().getScheduler();
if (timeOut != 0) { if (timeOut != 0) {
BukkitTask id = scheduler.runTaskLaterAsynchronously(plugin, BukkitTask id = scheduler.runTaskLater(plugin, new TimeoutTask(plugin, name, player), timeOut);
new TimeoutTask(plugin, name, player), timeOut);
limboPlayer.setTimeoutTaskId(id); limboPlayer.setTimeoutTaskId(id);
} }
limboPlayer.setMessageTaskId(scheduler.runTaskAsynchronously(plugin, limboPlayer.setMessageTaskId(scheduler.runTask(plugin,
new MessageTask(plugin, name, m.retrieve(MessageKey.REGISTER_MESSAGE), interval))); new MessageTask(plugin, name, MessageKey.REGISTER_MESSAGE, interval)));
m.send(player, MessageKey.UNREGISTERED_SUCCESS); m.send(player, MessageKey.UNREGISTERED_SUCCESS);
ConsoleLogger.info(player.getDisplayName() + " unregistered himself"); ConsoleLogger.info(player.getDisplayName() + " unregistered himself");
return; return;

View File

@ -82,4 +82,13 @@ public abstract class CustomConfiguration extends YamlConfiguration {
} }
return false; return false;
} }
public boolean containsAll(String... paths) {
for (String path : paths) {
if (!contains(path)) {
return false;
}
}
return true;
}
} }

View File

@ -1,96 +0,0 @@
package fr.xephi.authme.settings;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
/**
* @author Xephi59
* @version $Revision: 1.0 $
*/
public class OtherAccounts extends CustomConfiguration {
private static OtherAccounts others = null;
public OtherAccounts() {
super(new File("." + File.separator + "plugins" + File.separator + "AuthMe" + File.separator + "otheraccounts.yml"));
others = this;
load();
save();
}
/**
* Method getInstance.
*
* @return OtherAccounts
*/
public static OtherAccounts getInstance() {
if (others == null) {
others = new OtherAccounts();
}
return others;
}
/**
* Method clear.
*
* @param uuid UUID
*/
public void clear(UUID uuid) {
set(uuid.toString(), new ArrayList<String>());
save();
}
/**
* Method addPlayer.
*
* @param uuid UUID
*/
public void addPlayer(UUID uuid) {
try {
Player player = Bukkit.getPlayer(uuid);
if (player == null)
return;
if (!this.getStringList(uuid.toString()).contains(player.getName())) {
this.getStringList(uuid.toString()).add(player.getName());
save();
}
} catch (NoSuchMethodError | Exception e) {
//ignore
}
}
/**
* Method removePlayer.
*
* @param uuid UUID
*/
public void removePlayer(UUID uuid) {
try {
Player player = Bukkit.getPlayer(uuid);
if (player == null)
return;
if (this.getStringList(uuid.toString()).contains(player.getName())) {
this.getStringList(uuid.toString()).remove(player.getName());
save();
}
} catch (NoSuchMethodError | Exception e) {
//ignore
}
}
/**
* Method getAllPlayersByUUID.
*
* @param uuid UUID
*
* @return StringList
*/
public List<String> getAllPlayersByUUID(UUID uuid) {
return this.getStringList(uuid.toString());
}
}

View File

@ -60,7 +60,7 @@ public final class Settings {
useCaptcha, emailRegistration, multiverse, bungee, useCaptcha, emailRegistration, multiverse, bungee,
banUnsafeIp, doubleEmailCheck, sessionExpireOnIpChange, banUnsafeIp, doubleEmailCheck, sessionExpireOnIpChange,
disableSocialSpy, useEssentialsMotd, usePurge, disableSocialSpy, useEssentialsMotd, usePurge,
purgePlayerDat, purgeEssentialsFile, supportOldPassword, purgePlayerDat, purgeEssentialsFile,
purgeLimitedCreative, purgeAntiXray, purgePermissions, purgeLimitedCreative, purgeAntiXray, purgePermissions,
enableProtection, enableAntiBot, recallEmail, useWelcomeMessage, enableProtection, enableAntiBot, recallEmail, useWelcomeMessage,
broadcastWelcomeMessage, forceRegKick, forceRegLogin, broadcastWelcomeMessage, forceRegKick, forceRegLogin,
@ -72,19 +72,16 @@ public final class Settings {
getMySQLColumnGroup, unRegisteredGroup, getMySQLColumnGroup, unRegisteredGroup,
backupWindowsPath, getRegisteredGroup, backupWindowsPath, getRegisteredGroup,
rakamakUsers, rakamakUsersIp, getmailAccount, defaultWorld, rakamakUsers, rakamakUsersIp, getmailAccount, defaultWorld,
getPhpbbPrefix, getWordPressPrefix,
spawnPriority, crazyloginFileName, getPassRegex, sendPlayerTo; spawnPriority, crazyloginFileName, getPassRegex, sendPlayerTo;
public static int getWarnMessageInterval, getSessionTimeout, public static int getWarnMessageInterval, getSessionTimeout,
getRegistrationTimeout, getMaxNickLength, getMinNickLength, getRegistrationTimeout, getMaxNickLength, getMinNickLength,
getPasswordMinLen, getMovementRadius, getmaxRegPerIp, getPasswordMinLen, getMovementRadius, getmaxRegPerIp,
getNonActivatedGroup, passwordMaxLength, getRecoveryPassLength, getNonActivatedGroup, passwordMaxLength, getRecoveryPassLength,
getMailPort, maxLoginTry, captchaLength, saltLength, getMailPort, maxLoginTry, captchaLength, saltLength,
getmaxRegPerEmail, bCryptLog2Rounds, getPhpbbGroup, getmaxRegPerEmail, bCryptLog2Rounds,
antiBotSensibility, antiBotDuration, delayRecall, getMaxLoginPerIp, antiBotSensibility, antiBotDuration, delayRecall, getMaxLoginPerIp,
getMaxJoinPerIp; getMaxJoinPerIp;
protected static FileConfiguration configFile; protected static FileConfiguration configFile;
private static AuthMe plugin;
private static Settings instance;
/** /**
* Constructor for Settings. * Constructor for Settings.
@ -92,29 +89,27 @@ public final class Settings {
* @param pl AuthMe * @param pl AuthMe
*/ */
public Settings(AuthMe pl) { public Settings(AuthMe pl) {
instance = this; configFile = pl.getConfig();
plugin = pl;
configFile = plugin.getConfig();
loadVariables(); loadVariables();
} }
public static void loadVariables() { private static void loadVariables() {
isPermissionCheckEnabled = load(PluginSettings.ENABLE_PERMISSION_CHECK); isPermissionCheckEnabled = load(PluginSettings.ENABLE_PERMISSION_CHECK);
isForcedRegistrationEnabled = configFile.getBoolean("settings.registration.force", true); isForcedRegistrationEnabled = configFile.getBoolean("settings.registration.force", true);
isRegistrationEnabled = configFile.getBoolean("settings.registration.enabled", true); isRegistrationEnabled = configFile.getBoolean("settings.registration.enabled", true);
isTeleportToSpawnEnabled = configFile.getBoolean("settings.restrictions.teleportUnAuthedToSpawn", false); isTeleportToSpawnEnabled = load(RestrictionSettings.TELEPORT_UNAUTHED_TO_SPAWN);
getWarnMessageInterval = configFile.getInt("settings.registration.messageInterval", 5); getWarnMessageInterval = load(RegistrationSettings.MESSAGE_INTERVAL);
isSessionsEnabled = configFile.getBoolean("settings.sessions.enabled", false); isSessionsEnabled = load(PluginSettings.SESSIONS_ENABLED);
getSessionTimeout = configFile.getInt("settings.sessions.timeout", 10); getSessionTimeout = configFile.getInt("settings.sessions.timeout", 10);
getRegistrationTimeout = configFile.getInt("settings.restrictions.timeout", 30); getRegistrationTimeout = load(RestrictionSettings.TIMEOUT);
isChatAllowed = configFile.getBoolean("settings.restrictions.allowChat", false); isChatAllowed = load(RestrictionSettings.ALLOW_CHAT);
getMaxNickLength = configFile.getInt("settings.restrictions.maxNicknameLength", 20); getMaxNickLength = configFile.getInt("settings.restrictions.maxNicknameLength", 20);
getMinNickLength = configFile.getInt("settings.restrictions.minNicknameLength", 3); getMinNickLength = configFile.getInt("settings.restrictions.minNicknameLength", 3);
getPasswordMinLen = configFile.getInt("settings.security.minPasswordLength", 4); getPasswordMinLen = configFile.getInt("settings.security.minPasswordLength", 4);
getNickRegex = configFile.getString("settings.restrictions.allowedNicknameCharacters", "[a-zA-Z0-9_?]*"); getNickRegex = configFile.getString("settings.restrictions.allowedNicknameCharacters", "[a-zA-Z0-9_?]*");
nickPattern = Pattern.compile(getNickRegex); nickPattern = Pattern.compile(getNickRegex);
isAllowRestrictedIp = configFile.getBoolean("settings.restrictions.AllowRestrictedUser", false); isAllowRestrictedIp = load(RestrictionSettings.ENABLE_RESTRICTED_USERS);
getRestrictedIp = configFile.getStringList("settings.restrictions.AllowedRestrictedUser"); getRestrictedIp = load(RestrictionSettings.ALLOWED_RESTRICTED_USERS);
isMovementAllowed = configFile.getBoolean("settings.restrictions.allowMovement", false); isMovementAllowed = configFile.getBoolean("settings.restrictions.allowMovement", false);
isRemoveSpeedEnabled = configFile.getBoolean("settings.restrictions.removeSpeed", true); isRemoveSpeedEnabled = configFile.getBoolean("settings.restrictions.removeSpeed", true);
getMovementRadius = configFile.getInt("settings.restrictions.allowedMovementRadius", 100); getMovementRadius = configFile.getInt("settings.restrictions.allowedMovementRadius", 100);
@ -172,7 +167,7 @@ public final class Settings {
useCaptcha = configFile.getBoolean("Security.captcha.useCaptcha", false); useCaptcha = configFile.getBoolean("Security.captcha.useCaptcha", false);
maxLoginTry = configFile.getInt("Security.captcha.maxLoginTry", 5); maxLoginTry = configFile.getInt("Security.captcha.maxLoginTry", 5);
captchaLength = configFile.getInt("Security.captcha.captchaLength", 5); captchaLength = configFile.getInt("Security.captcha.captchaLength", 5);
emailRegistration = configFile.getBoolean("settings.registration.enableEmailRegistrationSystem", false); emailRegistration = load(RegistrationSettings.USE_EMAIL_REGISTRATION);
saltLength = configFile.getInt("settings.security.doubleMD5SaltLength", 8); saltLength = configFile.getInt("settings.security.doubleMD5SaltLength", 8);
getmaxRegPerEmail = configFile.getInt("Email.maxRegPerEmail", 1); getmaxRegPerEmail = configFile.getInt("Email.maxRegPerEmail", 1);
multiverse = load(HooksSettings.MULTIVERSE); multiverse = load(HooksSettings.MULTIVERSE);
@ -190,10 +185,6 @@ public final class Settings {
purgePlayerDat = configFile.getBoolean("Purge.removePlayerDat", false); purgePlayerDat = configFile.getBoolean("Purge.removePlayerDat", false);
purgeEssentialsFile = configFile.getBoolean("Purge.removeEssentialsFile", false); purgeEssentialsFile = configFile.getBoolean("Purge.removeEssentialsFile", false);
defaultWorld = configFile.getString("Purge.defaultWorld", "world"); defaultWorld = configFile.getString("Purge.defaultWorld", "world");
getPhpbbPrefix = configFile.getString("ExternalBoardOptions.phpbbTablePrefix", "phpbb_");
getPhpbbGroup = configFile.getInt("ExternalBoardOptions.phpbbActivatedGroupId", 2);
supportOldPassword = configFile.getBoolean("settings.security.supportOldPasswordHash", false);
getWordPressPrefix = configFile.getString("ExternalBoardOptions.wordpressTablePrefix", "wp_");
purgeLimitedCreative = configFile.getBoolean("Purge.removeLimitedCreativesInventories", false); purgeLimitedCreative = configFile.getBoolean("Purge.removeLimitedCreativesInventories", false);
purgeAntiXray = configFile.getBoolean("Purge.removeAntiXRayFile", false); purgeAntiXray = configFile.getBoolean("Purge.removeAntiXRayFile", false);
purgePermissions = configFile.getBoolean("Purge.removePermissions", false); purgePermissions = configFile.getBoolean("Purge.removePermissions", false);
@ -211,15 +202,15 @@ public final class Settings {
countriesBlacklist = configFile.getStringList("Protection.countriesBlacklist"); countriesBlacklist = configFile.getStringList("Protection.countriesBlacklist");
broadcastWelcomeMessage = configFile.getBoolean("settings.broadcastWelcomeMessage", false); broadcastWelcomeMessage = configFile.getBoolean("settings.broadcastWelcomeMessage", false);
forceRegKick = configFile.getBoolean("settings.registration.forceKickAfterRegister", false); forceRegKick = configFile.getBoolean("settings.registration.forceKickAfterRegister", false);
forceRegLogin = configFile.getBoolean("settings.registration.forceLoginAfterRegister", false); forceRegLogin = load(RegistrationSettings.FORCE_LOGIN_AFTER_REGISTER);
spawnPriority = load(RestrictionSettings.SPAWN_PRIORITY); spawnPriority = load(RestrictionSettings.SPAWN_PRIORITY);
getMaxLoginPerIp = configFile.getInt("settings.restrictions.maxLoginPerIp", 0); getMaxLoginPerIp = load(RestrictionSettings.MAX_LOGIN_PER_IP);
getMaxJoinPerIp = configFile.getInt("settings.restrictions.maxJoinPerIp", 0); getMaxJoinPerIp = load(RestrictionSettings.MAX_JOIN_PER_IP);
checkVeryGames = configFile.getBoolean("VeryGames.enableIpCheck", false); checkVeryGames = load(HooksSettings.ENABLE_VERYGAMES_IP_CHECK);
removeJoinMessage = load(RegistrationSettings.REMOVE_JOIN_MESSAGE); removeJoinMessage = load(RegistrationSettings.REMOVE_JOIN_MESSAGE);
removeLeaveMessage = load(RegistrationSettings.REMOVE_LEAVE_MESSAGE); removeLeaveMessage = load(RegistrationSettings.REMOVE_LEAVE_MESSAGE);
delayJoinMessage = load(RegistrationSettings.DELAY_JOIN_MESSAGE); delayJoinMessage = load(RegistrationSettings.DELAY_JOIN_MESSAGE);
noTeleport = configFile.getBoolean("settings.restrictions.noTeleport", false); noTeleport = load(RestrictionSettings.NO_TELEPORT);
crazyloginFileName = configFile.getString("Converter.CrazyLogin.fileName", "accounts.db"); crazyloginFileName = configFile.getString("Converter.CrazyLogin.fileName", "accounts.db");
getPassRegex = configFile.getString("settings.restrictions.allowedPasswordCharacters", "[\\x21-\\x7E]*"); getPassRegex = configFile.getString("settings.restrictions.allowedPasswordCharacters", "[\\x21-\\x7E]*");
applyBlindEffect = configFile.getBoolean("settings.applyBlindEffect", false); applyBlindEffect = configFile.getBoolean("settings.applyBlindEffect", false);

View File

@ -2,7 +2,6 @@ package fr.xephi.authme.settings;
import com.onarandombox.MultiverseCore.api.MVWorldManager; import com.onarandombox.MultiverseCore.api.MVWorldManager;
import fr.xephi.authme.AuthMe; import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.PlayerCache; import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.util.StringUtils; import fr.xephi.authme.util.StringUtils;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@ -73,34 +72,32 @@ public class Spawn extends CustomConfiguration {
} }
public Location getSpawn() { public Location getSpawn() {
try { if (containsAll("spawn.world", "spawn.x", "spawn.y", "spawn.z", "spawn.yaw", "spawn.pitch")) {
String worldName = getString("spawn.world"); String worldName = getString("spawn.world");
World world = Bukkit.getWorld(worldName); World world = Bukkit.getWorld(worldName);
if (StringUtils.isEmpty(worldName) || world == null) { if (!StringUtils.isEmpty(worldName) && world != null) {
return null; return new Location(
world, getDouble("spawn.x"), getDouble("spawn.y"), getDouble("spawn.z"),
Float.parseFloat(getString("spawn.yaw")), Float.parseFloat(getString("spawn.pitch"))
);
} }
return new Location(world, getDouble("spawn.x"), getDouble("spawn.y"), getDouble("spawn.z"),
Float.parseFloat(getString("spawn.yaw")), Float.parseFloat(getString("spawn.pitch")));
} catch (NumberFormatException e) {
ConsoleLogger.writeStackTrace(e);
return null;
} }
return null;
} }
public Location getFirstSpawn() { public Location getFirstSpawn() {
try { if (containsAll("firstspawn.world", "firstspawn.x", "firstspawn.y",
String worldName; "firstspawn.z", "firstspawn.yaw", "firstspawn.pitch")) {
World world; String worldName = getString("firstspawn.world");
if (StringUtils.isEmpty(worldName = getString("firstspawn.world")) || World world = Bukkit.getWorld(worldName);
(world = Bukkit.getWorld(worldName)) == null) { if (!StringUtils.isEmpty(worldName) && world != null) {
return null; return new Location(
world, getDouble("firstspawn.x"), getDouble("firstspawn.y"), getDouble("firstspawn.z"),
Float.parseFloat(getString("firstspawn.yaw")), Float.parseFloat(getString("firstspawn.pitch"))
);
} }
return new Location(world, getDouble("firstspawn.x"), getDouble("firstspawn.y"), getDouble("firstspawn.z"),
Float.parseFloat(getString("firstspawn.yaw")), Float.parseFloat(getString("firstspawn.pitch")));
} catch (NumberFormatException e) {
ConsoleLogger.writeStackTrace(e);
return null;
} }
return null;
} }
// Return the spawn location of a player // Return the spawn location of a player

View File

@ -39,7 +39,7 @@ public class RegistrationSettings implements SettingsClass {
newProperty("settings.registration.doubleEmailCheck", false); newProperty("settings.registration.doubleEmailCheck", false);
@Comment({ @Comment({
"Do we force kicking player after a successful registration?", "Do we force kick a player after a successful registration?",
"Do not use with login feature below"}) "Do not use with login feature below"})
public static final Property<Boolean> FORCE_KICK_AFTER_REGISTER = public static final Property<Boolean> FORCE_KICK_AFTER_REGISTER =
newProperty("settings.registration.forceKickAfterRegister", false); newProperty("settings.registration.forceKickAfterRegister", false);

View File

@ -64,7 +64,7 @@ public class RestrictionSettings implements SettingsClass {
@Comment({ @Comment({
"To activate the restricted user feature you need", "To activate the restricted user feature you need",
"to enable this option and configure the AllowedRestrctedUser field."}) "to enable this option and configure the AllowedRestrictedUser field."})
public static final Property<Boolean> ENABLE_RESTRICTED_USERS = public static final Property<Boolean> ENABLE_RESTRICTED_USERS =
newProperty("settings.restrictions.AllowRestrictedUser", false); newProperty("settings.restrictions.AllowRestrictedUser", false);

View File

@ -53,12 +53,12 @@ public class ChangePasswordTask implements Runnable {
@Override @Override
public void run() { public void run() {
ByteArrayDataOutput out = ByteStreams.newDataOutput(); ByteArrayDataOutput out = ByteStreams.newDataOutput();
out.writeUTF("Forward"); out.writeUTF("Forward");
out.writeUTF("ALL"); out.writeUTF("ALL");
out.writeUTF("AuthMe"); out.writeUTF("AuthMe");
out.writeUTF("changepassword;" + name + ";" + hash + ";" + salt); out.writeUTF("changepassword;" + name + ";" + hash + ";" + salt);
player.sendPluginMessage(plugin, "BungeeCord", out.toByteArray()); player.sendPluginMessage(plugin, "BungeeCord", out.toByteArray());
} }
}); });
} }

View File

@ -3,6 +3,7 @@ package fr.xephi.authme.task;
import fr.xephi.authme.AuthMe; import fr.xephi.authme.AuthMe;
import fr.xephi.authme.cache.auth.PlayerCache; import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.cache.limbo.LimboCache; import fr.xephi.authme.cache.limbo.LimboCache;
import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.util.Utils; import fr.xephi.authme.util.Utils;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitTask; import org.bukkit.scheduler.BukkitTask;
@ -24,32 +25,31 @@ public class MessageTask implements Runnable {
* @param strings String[] * @param strings String[]
* @param interval int * @param interval int
*/ */
public MessageTask(AuthMe plugin, String name, String[] strings, public MessageTask(AuthMe plugin, String name, String[] strings, int interval) {
int interval) {
this.plugin = plugin; this.plugin = plugin;
this.name = name; this.name = name;
this.msg = strings; this.msg = strings;
this.interval = interval; this.interval = interval;
} }
/** public MessageTask(AuthMe plugin, String name, MessageKey messageKey, int interval) {
* Method run. this(plugin, name, plugin.getMessages().retrieve(messageKey), interval);
* }
* @see java.lang.Runnable#run()
*/
@Override @Override
public void run() { public void run() {
if (PlayerCache.getInstance().isAuthenticated(name)) if (PlayerCache.getInstance().isAuthenticated(name)) {
return; return;
}
for (Player player : Utils.getOnlinePlayers()) { for (Player player : Utils.getOnlinePlayers()) {
if (player.getName().toLowerCase().equals(name)) { if (player.getName().equalsIgnoreCase(name)) {
for (String ms : msg) { for (String ms : msg) {
player.sendMessage(ms); player.sendMessage(ms);
} }
BukkitTask late = plugin.getServer().getScheduler().runTaskLaterAsynchronously(plugin, this, interval * 20); BukkitTask nextTask = plugin.getServer().getScheduler().runTaskLater(plugin, this, interval * 20);
if (LimboCache.getInstance().hasLimboPlayer(name)) { if (LimboCache.getInstance().hasLimboPlayer(name)) {
LimboCache.getInstance().getLimboPlayer(name).setMessageTaskId(late); LimboCache.getInstance().getLimboPlayer(name).setMessageTaskId(nextTask);
} }
return; return;
} }

View File

@ -4,14 +4,10 @@ import fr.xephi.authme.AuthMe;
import fr.xephi.authme.cache.auth.PlayerCache; import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.output.Messages; import fr.xephi.authme.output.Messages;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
/**
*/
public class TimeoutTask implements Runnable { public class TimeoutTask implements Runnable {
private final AuthMe plugin;
private final String name; private final String name;
private final Messages m; private final Messages m;
private final Player player; private final Player player;
@ -25,38 +21,14 @@ public class TimeoutTask implements Runnable {
*/ */
public TimeoutTask(AuthMe plugin, String name, Player player) { public TimeoutTask(AuthMe plugin, String name, Player player) {
this.m = plugin.getMessages(); this.m = plugin.getMessages();
this.plugin = plugin;
this.name = name; this.name = name;
this.player = player; this.player = player;
} }
/**
* Method getName.
*
* @return String
*/
public String getName() {
return name;
}
/**
* Method run.
*
* @see java.lang.Runnable#run()
*/
@Override @Override
public void run() { public void run() {
if (PlayerCache.getInstance().isAuthenticated(name)) { if (!PlayerCache.getInstance().isAuthenticated(name)) {
return; player.kickPlayer(m.retrieveSingle(MessageKey.LOGIN_TIMEOUT_ERROR));
} }
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
@Override
public void run() {
if (player.isOnline()) {
player.kickPlayer(m.retrieveSingle(MessageKey.LOGIN_TIMEOUT_ERROR));
}
}
});
} }
} }

View File

@ -5,6 +5,8 @@ import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.converter.ForceFlatToSqlite; import fr.xephi.authme.converter.ForceFlatToSqlite;
import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.datasource.DataSourceType; import fr.xephi.authme.datasource.DataSourceType;
import fr.xephi.authme.datasource.FlatFile;
import fr.xephi.authme.datasource.SQLite;
import fr.xephi.authme.security.HashAlgorithm; import fr.xephi.authme.security.HashAlgorithm;
import fr.xephi.authme.security.crypts.HashedPassword; import fr.xephi.authme.security.crypts.HashedPassword;
import fr.xephi.authme.security.crypts.SHA256; import fr.xephi.authme.security.crypts.SHA256;
@ -58,12 +60,17 @@ public final class MigrationService {
if (DataSourceType.FILE == settings.getProperty(DatabaseSettings.BACKEND)) { if (DataSourceType.FILE == settings.getProperty(DatabaseSettings.BACKEND)) {
ConsoleLogger.showError("FlatFile backend has been detected and is now deprecated; it will be changed " ConsoleLogger.showError("FlatFile backend has been detected and is now deprecated; it will be changed "
+ "to SQLite... Connection will be impossible until conversion is done!"); + "to SQLite... Connection will be impossible until conversion is done!");
ForceFlatToSqlite converter = new ForceFlatToSqlite(dataSource, settings); FlatFile flatFile = (FlatFile) dataSource;
DataSource result = converter.run(); try {
if (result == null) { SQLite sqlite = new SQLite(settings);
throw new IllegalStateException("Error during conversion from flatfile to SQLite"); ForceFlatToSqlite converter = new ForceFlatToSqlite(flatFile, sqlite);
} else { converter.run();
return result; settings.setProperty(DatabaseSettings.BACKEND, DataSourceType.SQLITE);
settings.save();
return sqlite;
} catch (Exception e) {
ConsoleLogger.logException("Error during conversion from Flatfile to SQLite", e);
throw new IllegalStateException(e);
} }
} }
return null; return null;

View File

@ -2,15 +2,13 @@ package fr.xephi.authme.util;
import java.text.DecimalFormat; import java.text.DecimalFormat;
/**
*/
@SuppressWarnings("UnusedDeclaration")
public class Profiler { public class Profiler {
/** /**
* Defines the past time in milliseconds. * Defines the past time in milliseconds.
*/ */
private long time = 0; private long time = 0;
/** /**
* Defines the time in milliseconds the profiler last started at. * Defines the time in milliseconds the profiler last started at.
*/ */

View File

@ -154,8 +154,7 @@ public final class Utils {
public static boolean isUnrestricted(Player player) { public static boolean isUnrestricted(Player player) {
return Settings.isAllowRestrictedIp return Settings.isAllowRestrictedIp
&& !Settings.getUnrestrictedName.isEmpty() && Settings.getUnrestrictedName.contains(player.getName().toLowerCase());
&& (Settings.getUnrestrictedName.contains(player.getName().toLowerCase()));
} }
public static void packCoords(double x, double y, double z, String w, final Player pl) { public static void packCoords(double x, double y, double z, String w, final Player pl) {
@ -216,8 +215,7 @@ public final class Utils {
ConsoleLogger.showError("Unknown list of online players of type " + type); ConsoleLogger.showError("Unknown list of online players of type " + type);
} }
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
ConsoleLogger.showError("Could not retrieve list of online players: [" ConsoleLogger.logException("Could not retrieve list of online players:", e);
+ e.getClass().getName() + "] " + e.getMessage());
} }
return Collections.emptyList(); return Collections.emptyList();
} }

View File

@ -1,5 +1,5 @@
unknown_user: '&cBenutzer ist nicht in der Datenbank' unknown_user: '&cBenutzer ist nicht in der Datenbank'
unsafe_spawn: '&cDeine Logoutposition war unsicher, du wurdest zum Spawn teleportiert' unsafe_spawn: '&cDeine Logoutposition war unsicher, Du wurdest zum Spawn teleportiert'
not_logged_in: '&cNicht eingeloggt!' not_logged_in: '&cNicht eingeloggt!'
reg_voluntarily: 'Du kannst dich mit folgendem Befehl registrieren "/register <passwort> <passwortBestätigen>"' reg_voluntarily: 'Du kannst dich mit folgendem Befehl registrieren "/register <passwort> <passwortBestätigen>"'
usage_log: '&cBenutze: /login <passwort>' usage_log: '&cBenutze: /login <passwort>'
@ -9,11 +9,11 @@ reg_disabled: '&cRegistrierungen sind deaktiviert'
valid_session: '&2Erfolgreich eingeloggt!' valid_session: '&2Erfolgreich eingeloggt!'
login: '&2Erfolgreich eingeloggt!' login: '&2Erfolgreich eingeloggt!'
vb_nonActiv: '&cDein Account wurde noch nicht aktiviert. Bitte prüfe Deine E-Mails!' vb_nonActiv: '&cDein Account wurde noch nicht aktiviert. Bitte prüfe Deine E-Mails!'
user_regged: '&cBenutzername ist schon vergeben' user_regged: '&cDieser Benutzername ist schon vergeben'
usage_reg: '&cBenutze: /register <passwort> <passwortBestätigen>' usage_reg: '&cBenutze: /register <passwort> <passwortBestätigen>'
max_reg: '&cDu hast die maximale Anzahl an Accounts erreicht' max_reg: '&cDu hast die maximale Anzahl an Accounts erreicht.'
no_perm: '&4Du hast keine Rechte, um diese Aktion auszuführen!' no_perm: '&4Du hast keine Rechte, um diese Aktion auszuführen!'
error: '&4Ein Fehler ist aufgetreten. Bitte kontaktiere einen Administrator' error: '&4Ein Fehler ist aufgetreten. Bitte kontaktiere einen Administrator.'
login_msg: '&cBitte logge Dich ein mit "/login <passwort>"' login_msg: '&cBitte logge Dich ein mit "/login <passwort>"'
reg_msg: '&3Bitte registriere Dich mit "/register <passwort> <passwortBestätigen>"' reg_msg: '&3Bitte registriere Dich mit "/register <passwort> <passwortBestätigen>"'
reg_email_msg: '&3Bitte registriere Dich mit "/register <email> <emailBestätigen>"' reg_email_msg: '&3Bitte registriere Dich mit "/register <email> <emailBestätigen>"'
@ -21,44 +21,43 @@ usage_unreg: '&cBenutze: /unregister <passwort>'
pwd_changed: '&2Passwort geändert!' pwd_changed: '&2Passwort geändert!'
user_unknown: '&cBenutzername nicht registriert!' user_unknown: '&cBenutzername nicht registriert!'
password_error: '&cPasswörter stimmen nicht überein!' password_error: '&cPasswörter stimmen nicht überein!'
password_error_nick: '&cDu kannst nicht deinen Namen als Passwort nutzen!' password_error_nick: '&cDu kannst nicht Deinen Namen als Passwort nutzen!'
password_error_unsafe: '&cDu kannst nicht unsichere Passwörter nutzen!' password_error_unsafe: '&cDu kannst nicht unsichere Passwörter nutzen!'
invalid_session: '&cUngültige Session. Bitte starte das Spiel neu oder warte, bis die Session abgelaufen ist' invalid_session: '&cUngültige Session. Bitte starte das Spiel neu oder warte, bis die Session abgelaufen ist'
reg_only: '&4Nur für registrierte Spieler! Bitte besuche http://example.com zum registrieren' reg_only: '&4Nur für registrierte Spieler! Bitte besuche http://example.com zum Registrieren'
logged_in: '&cBereits eingeloggt!' logged_in: '&cBereits eingeloggt!'
logout: '&2Erfolgreich ausgeloggt' logout: '&2Erfolgreich ausgeloggt'
same_nick: '&4Jemand mit diesem Namen spielt bereits auf dem Server!' same_nick: '&4Jemand mit diesem Namen spielt bereits auf dem Server!'
registered: '&2Erfolgreich registriert!' registered: '&2Erfolgreich registriert!'
pass_len: '&cDein Passwort ist zu kurz oder zu lang!' pass_len: '&cDein Passwort ist zu kurz oder zu lang!'
reload: '&2Konfiguration und Datenbank wurden erfolgreich neu geladen' reload: '&2Konfiguration und Datenbank wurden erfolgreich neu geladen.'
timeout: '&4Zeitüberschreitung beim Login' timeout: '&4Zeitüberschreitung beim Login'
usage_changepassword: '&cBenutze: /changepassword <altesPasswort> <neuesPasswort>' usage_changepassword: '&cBenutze: /changepassword <altesPasswort> <neuesPasswort>'
name_len: '&4Dein Nickname ist zu kurz oder zu lang' name_len: '&4Dein Nickname ist zu kurz oder zu lang.'
regex: '&4Dein Nickname enthält nicht erlaubte Zeichen. Zulässige Zeichen: REG_EX' regex: '&4Dein Nickname enthält nicht erlaubte Zeichen. Zulässige Zeichen: REG_EX'
add_email: '&3Bitte hinterlege Deine E-Mail Adresse: /email add <deineEmail> <emailBestätigen>' add_email: '&3Bitte hinterlege Deine E-Mail-Adresse: /email add <deineEmail> <emailBestätigen>'
recovery_email: '&3Passwort vergessen? Nutze "/email recovery <deineEmail>" für ein neues Passwort' recovery_email: '&3Passwort vergessen? Nutze "/email recovery <deineEmail>" für ein neues Passwort'
usage_captcha: '&3Um dich einzuloggen, tippe dieses Captcha so ein: /captcha <theCaptcha>' usage_captcha: '&3Um dich einzuloggen, tippe dieses Captcha so ein: /captcha <theCaptcha>'
wrong_captcha: '&cFalsches Captcha, bitte nutze: /captcha THE_CAPTCHA' wrong_captcha: '&cFalsches Captcha, bitte nutze: /captcha THE_CAPTCHA'
valid_captcha: '&2Das Captcha ist korrekt!' valid_captcha: '&2Das Captcha ist korrekt!'
kick_forvip: '&3Ein VIP Spieler hat den vollen Server betreten!' kick_forvip: '&3Ein VIP-Spieler hat den vollen Server betreten!'
kick_fullserver: '&4Der Server ist momentan voll, Sorry!' kick_fullserver: '&4Der Server ist momentan voll, Sorry!'
usage_email_add: '&cBenutze: /email add <email> <bestätigeEmail>' usage_email_add: '&cBenutze: /email add <email> <bestätigeEmail>'
usage_email_change: '&cBenutze: /email change <alteEmail> <neueEmail>' usage_email_change: '&cBenutze: /email change <alteEmail> <neueEmail>'
usage_email_recovery: '&cBenutze: /email recovery <Email>' usage_email_recovery: '&cBenutze: /email recovery <Email>'
new_email_invalid: '&cDie neue Email ist ungültig!' new_email_invalid: '&cDie neue E-Mail ist ungültig!'
old_email_invalid: '&cDie alte Email ist ungültig!' old_email_invalid: '&cDie alte E-Mail ist ungültig!'
email_invalid: '&cUngültige Email' email_invalid: '&cUngültige E-Mail!'
email_added: '&2Email hinzugefügt!' email_added: '&2E-Mail hinzugefügt!'
email_confirm: '&cBitte bestätige deine Email!' email_confirm: '&cBitte bestätige Deine E-Mail!'
email_changed: '&2Email aktualisiert!' email_changed: '&2E-Mail aktualisiert!'
email_send: '&2Wiederherstellungs-Email wurde gesendet!' email_send: '&2Wiederherstellungs-E-Mail wurde gesendet!'
email_exists: '&cEine Wiederherstellungs-Email wurde bereits versandt! Nutze folgenden Befehl um eine neue Email zu versenden:' email_exists: '&cEine Wiederherstellungs-E-Mail wurde bereits versandt! Nutze folgenden Befehl um eine neue E-Mail zu versenden:'
country_banned: '&4Dein Land ist gesperrt' country_banned: '&4Dein Land ist gesperrt!'
antibot_auto_enabled: '&4[AntiBotService] AntiBotMod wurde aufgrund hoher Netzauslastung automatisch aktiviert!' antibot_auto_enabled: '&4[AntiBotService] AntiBotMod wurde aufgrund hoher Netzauslastung automatisch aktiviert!'
antibot_auto_disabled: '&2[AntiBotService] AntiBotMod wurde nach %m Minuten deaktiviert, hoffentlich ist die Invasion vorbei' antibot_auto_disabled: '&2[AntiBotService] AntiBotMod wurde nach %m Minuten deaktiviert, hoffentlich ist die Invasion vorbei.'
kick_antibot: 'AntiBotMod ist aktiviert! Bitte warte einige Minuten, bevor du dich mit dem Server verbindest' kick_antibot: 'AntiBotMod ist aktiviert! Bitte warte einige Minuten, bevor Du Dich mit dem Server verbindest.'
# TODO two_factor_create: Missing tag %url two_factor_create: '&2Dein geheimer Code ist %code. Du kannst ihn hier abfragen: %url'
two_factor_create: '&2Dein geheimer Code ist %code' email_already_used: '&4Diese E-Mail-Adresse wird bereits genutzt.'
# TODO email_already_used: '&4The email address is already being used' invalid_name_case: 'Dein registrierter Benutzername ist &2%valid&f - nicht &4%invalid&f.'
# TODO invalid_name_case: 'You should join using username %valid, not %invalid.' not_owner_error: 'Du bist nicht der Besitzer dieses Accounts. Bitte wähle einen anderen Namen!'
# TODO not_owner_error: 'You are not the owner of this account. Please try another name!'

View File

@ -12,7 +12,7 @@ login: '&2Successful login!'
vb_nonActiv: '&cYour account isn''t activated yet, please check your emails!' vb_nonActiv: '&cYour account isn''t activated yet, please check your emails!'
user_regged: '&cYou already have registered this username!' user_regged: '&cYou already have registered this username!'
usage_reg: '&cUsage: /register <password> <ConfirmPassword>' usage_reg: '&cUsage: /register <password> <ConfirmPassword>'
max_reg: '&cYou have exceeded the maximum number of registrations for your connection!' max_reg: '&cYou have exceeded the maximum number of registrations (%reg_count/%max_acc %reg_names) for your connection!'
no_perm: '&4You don''t have the permission to perform this action!' no_perm: '&4You don''t have the permission to perform this action!'
error: '&4An unexpected error occurred, please contact an administrator!' error: '&4An unexpected error occurred, please contact an administrator!'
login_msg: '&cPlease, login with the command "/login <password>"' login_msg: '&cPlease, login with the command "/login <password>"'
@ -59,5 +59,5 @@ antibot_auto_enabled: '&4[AntiBotService] AntiBot enabled due to the huge number
antibot_auto_disabled: '&2[AntiBotService] AntiBot disabled disabled after %m minutes!' antibot_auto_disabled: '&2[AntiBotService] AntiBot disabled disabled after %m minutes!'
email_already_used: '&4The email address is already being used' email_already_used: '&4The email address is already being used'
two_factor_create: '&2Your secret code is %code. You can scan it from here %url' two_factor_create: '&2Your secret code is %code. You can scan it from here %url'
not_owner_error: 'You are not the owner of this account. Please try another name!' not_owner_error: 'You are not the owner of this account. Please choose another name!'
invalid_name_case: 'You should join using username %valid, not %invalid.' invalid_name_case: 'You should join using username %valid, not %invalid.'

View File

@ -1,4 +1,4 @@
package fr.xephi.authme.datasource; package fr.xephi.authme;
import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.security.crypts.HashedPassword; import fr.xephi.authme.security.crypts.HashedPassword;

View File

@ -1,14 +1,13 @@
package fr.xephi.authme.command; package fr.xephi.authme.command;
import static fr.xephi.authme.permission.DefaultPermission.OP_ONLY; import fr.xephi.authme.permission.AdminPermission;
import static org.hamcrest.Matchers.equalTo; import fr.xephi.authme.permission.PermissionNode;
import static org.hamcrest.Matchers.not; import fr.xephi.authme.util.StringUtils;
import static org.hamcrest.Matchers.nullValue; import fr.xephi.authme.util.WrapperMock;
import static org.junit.Assert.assertThat; import org.junit.BeforeClass;
import static org.junit.Assert.fail; import org.junit.Test;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@ -17,13 +16,12 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.junit.BeforeClass; import static fr.xephi.authme.permission.DefaultPermission.OP_ONLY;
import org.junit.Test; import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.not;
import fr.xephi.authme.permission.AdminPermission; import static org.hamcrest.Matchers.nullValue;
import fr.xephi.authme.permission.PermissionNode; import static org.junit.Assert.assertThat;
import fr.xephi.authme.util.StringUtils; import static org.junit.Assert.fail;
import fr.xephi.authme.util.WrapperMock;
/** /**
* Test for {@link CommandInitializer} to guarantee the integrity of the defined commands. * Test for {@link CommandInitializer} to guarantee the integrity of the defined commands.
@ -241,15 +239,11 @@ public class CommandInitializerTest {
public void shouldNotHavePlayerPermissionIfDefaultsToOpOnly() { public void shouldNotHavePlayerPermissionIfDefaultsToOpOnly() {
// given // given
BiConsumer adminPermissionChecker = new BiConsumer() { BiConsumer adminPermissionChecker = new BiConsumer() {
// The only exception to this check is the force login command, which should default to OP_ONLY
// but semantically it is a player permission
final List<String> forceLoginLabels = Arrays.asList("forcelogin", "login");
@Override @Override
public void accept(CommandDescription command, int depth) { public void accept(CommandDescription command, int depth) {
CommandPermissions permissions = command.getCommandPermissions(); CommandPermissions permissions = command.getCommandPermissions();
if (permissions != null && OP_ONLY.equals(permissions.getDefaultPermission())) { if (permissions != null && OP_ONLY.equals(permissions.getDefaultPermission())) {
if (!hasAdminNode(permissions) && !command.getLabels().equals(forceLoginLabels)) { if (!hasAdminNode(permissions)) {
fail("The command with labels " + command.getLabels() + " has OP_ONLY default " fail("The command with labels " + command.getLabels() + " has OP_ONLY default "
+ "permission but no permission node on admin level"); + "permission but no permission node on admin level");
} }

View File

@ -0,0 +1,72 @@
package fr.xephi.authme.converter;
import com.google.common.io.Files;
import fr.xephi.authme.ConsoleLoggerTestInitializer;
import fr.xephi.authme.TestHelper;
import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.datasource.FlatFile;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.mockito.ArgumentCaptor;
import java.io.File;
import java.io.IOException;
import java.util.List;
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.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
/**
* Test for {@link ForceFlatToSqlite}.
*/
public class ForceFlatToSqliteTest {
@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
private FlatFile flatFile;
@BeforeClass
public static void setup() {
ConsoleLoggerTestInitializer.setupLogger();
}
@Before
public void copyFile() throws IOException {
File source = TestHelper.getJarFile("/datasource-integration/flatfile-test.txt");
File destination = temporaryFolder.newFile();
Files.copy(source, destination);
flatFile = new FlatFile(destination);
}
@Test
public void shouldConvertToSqlite() {
// given
DataSource dataSource = mock(DataSource.class);
ForceFlatToSqlite converter = new ForceFlatToSqlite(flatFile, dataSource);
// when
converter.run();
// then
ArgumentCaptor<PlayerAuth> authCaptor = ArgumentCaptor.forClass(PlayerAuth.class);
verify(dataSource, times(7)).saveAuth(authCaptor.capture());
List<PlayerAuth> auths = authCaptor.getAllValues();
assertThat(auths, hasItem(hasAuthBasicData("bobby", "Bobby", "your@email.com", "123.45.67.89")));
assertThat(auths, hasItem(hasAuthLocation(1.05, 2.1, 4.2, "world")));
assertThat(auths, hasItem(hasAuthBasicData("user", "user", "user@example.org", "34.56.78.90")));
assertThat(auths, hasItem(hasAuthLocation(124.1, 76.3, -127.8, "nether")));
assertThat(auths, hasItem(hasAuthBasicData("eightfields", "eightFields", "your@email.com", "6.6.6.66")));
assertThat(auths, hasItem(hasAuthLocation(8.8, 17.6, 26.4, "eightworld")));
}
}

View File

@ -4,15 +4,18 @@ import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.security.crypts.HashedPassword; import fr.xephi.authme.security.crypts.HashedPassword;
import org.junit.Test; import org.junit.Test;
import java.util.Arrays;
import java.util.List; import java.util.List;
import static fr.xephi.authme.datasource.AuthMeMatchers.equalToHash; import static fr.xephi.authme.AuthMeMatchers.equalToHash;
import static fr.xephi.authme.datasource.AuthMeMatchers.hasAuthBasicData; import static fr.xephi.authme.AuthMeMatchers.hasAuthBasicData;
import static fr.xephi.authme.datasource.AuthMeMatchers.hasAuthLocation; import static fr.xephi.authme.AuthMeMatchers.hasAuthLocation;
import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertThat; import static org.junit.Assert.assertThat;
import static org.junit.Assume.assumeThat;
/** /**
* Abstract class for data source integration tests. * Abstract class for data source integration tests.
@ -126,15 +129,9 @@ public abstract class AbstractDataSourceIntegrationTest {
// then // then
assertThat(response, equalTo(true)); assertThat(response, equalTo(true));
assertThat(authList, hasSize(2)); assertThat(authList, hasSize(2));
assertThat(authList, hasItem(hasAuthBasicData("bobby", "Bobby", "your@email.com", "123.45.67.89")));
assertThat(newAuthList, hasSize(3)); assertThat(newAuthList, hasSize(3));
boolean hasBobby = false; assertThat(newAuthList, hasItem(hasAuthBasicData("bobby", "Bobby", "your@email.com", "123.45.67.89")));
for (PlayerAuth auth : authList) {
if (auth.getNickname().equals("bobby")) {
hasBobby = true;
break;
}
}
assertThat(hasBobby, equalTo(true));
} }
@Test @Test
@ -201,4 +198,106 @@ public abstract class AbstractDataSourceIntegrationTest {
assertThat(dataSource.getAuth("user"), hasAuthLocation(143, -42.12, 29.47, "the_end")); assertThat(dataSource.getAuth("user"), hasAuthLocation(143, -42.12, 29.47, "the_end"));
} }
@Test
public void shouldDeletePlayers() {
// given
DataSource dataSource = getDataSource();
List<String> playersToDelete = Arrays.asList("bobby", "doesNotExist");
assumeThat(dataSource.getAccountsRegistered(), equalTo(2));
// when
dataSource.purgeBanned(playersToDelete);
// then
assertThat(dataSource.getAccountsRegistered(), equalTo(1));
assertThat(dataSource.isAuthAvailable("bobby"), equalTo(false));
assertThat(dataSource.isAuthAvailable("user"), equalTo(true));
}
@Test
public void shouldUpdateEmail() {
// given
DataSource dataSource = getDataSource();
String email = "new-user@mail.tld";
PlayerAuth userAuth = PlayerAuth.builder().name("user").email(email).build();
PlayerAuth invalidAuth = PlayerAuth.builder().name("invalid").email("addr@example.com").build();
// when
boolean response1 = dataSource.updateEmail(userAuth);
boolean response2 = dataSource.updateEmail(invalidAuth);
// then
assertThat(response1 && response2, equalTo(true));
assertThat(dataSource.getAllAuths(), hasItem(hasAuthBasicData("user", "user", email, "34.56.78.90")));
}
@Test
public void shouldUpdateIp() {
// given
DataSource dataSource = getDataSource();
String ip = "250.230.67.73";
// when
boolean response1 = dataSource.updateIp("bobby", ip);
boolean response2 = dataSource.updateIp("bogus", "123.123.123.123");
// then
assertThat(response1 && response2, equalTo(true));
assertThat(dataSource.getAllAuths(), hasItem(hasAuthBasicData("bobby", "Bobby", "your@email.com", ip)));
}
@Test
public void shouldCountAuths() {
// given
DataSource dataSource = getDataSource();
// when
int initialCount = dataSource.getAccountsRegistered();
for (int i = 0; i < 4; ++i) {
dataSource.saveAuth(PlayerAuth.builder().name("test-" + i).build());
}
int endCount = dataSource.getAccountsRegistered();
// then
assertThat(initialCount, equalTo(2));
assertThat(endCount, equalTo(6));
}
@Test
public void shouldGetAllUsersByIp() {
// given
DataSource dataSource = getDataSource();
// when
List<String> initialList = dataSource.getAllAuthsByIp("123.45.67.89");
List<String> emptyList = dataSource.getAllAuthsByIp("8.8.8.8");
for (int i = 0; i < 3; ++i) {
dataSource.saveAuth(PlayerAuth.builder().name("test-" + i).ip("123.45.67.89").build());
}
List<String> updatedList = dataSource.getAllAuthsByIp("123.45.67.89");
// then
assertThat(initialList, hasSize(1));
assertThat(initialList.get(0), equalTo("bobby"));
assertThat(emptyList, hasSize(0));
assertThat(updatedList, hasSize(4));
assertThat(updatedList, hasItem(equalTo("bobby")));
assertThat(updatedList, hasItem(equalTo("test-1")));
}
@Test
public void shouldUpdateRealName() {
// given
DataSource dataSource = getDataSource();
// when
boolean response1 = dataSource.updateRealName("bobby", "BOBBY");
boolean response2 = dataSource.updateRealName("notExists", "NOTEXISTS");
// then
assertThat(response1 && response2, equalTo(true));
assertThat(dataSource.getAuth("bobby"), hasAuthBasicData("bobby", "BOBBY", "your@email.com", "123.45.67.89"));
}
} }

View File

@ -0,0 +1,321 @@
package fr.xephi.authme.datasource;
import com.google.common.base.Objects;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import fr.xephi.authme.ConsoleLoggerTestInitializer;
import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.security.HashAlgorithm;
import fr.xephi.authme.security.crypts.HashedPassword;
import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.domain.Property;
import fr.xephi.authme.settings.properties.SecuritySettings;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.Blob;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.mockito.BDDMockito.given;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
/**
* Test class which runs through a datasource implementation and verifies that all
* instances of {@link AutoCloseable} that are created in the calls are closed again.
* <p>
* Instead of an actual connection to a datasource, we pass a mock Connection object
* which is set to create additional mocks on demand for Statement and ResultSet objects.
* This test ensures that all such objects that are created will be closed again by
* keeping a list of mocks ({@link #closeables}) and then verifying that all have been
* closed {@link #verifyHaveMocksBeenClosed()}.
*/
@RunWith(Parameterized.class)
public abstract class AbstractResourceClosingTest {
/** List of DataSource method names not to test. */
private static final Set<String> IGNORED_METHODS = ImmutableSet.of("reload", "close", "getType");
/** Collection of values to use to call methods with the parameters they expect. */
private static final Map<Class<?>, Object> PARAM_VALUES = getDefaultParameters();
/**
* Custom list of hash algorithms to use to test a method. By default we define {@link HashAlgorithm#XFBCRYPT} as
* algorithms we use as a lot of methods execute additional statements in {@link MySQL}. If other algorithms
* have custom behaviors, they can be supplied in this map so it will be tested as well.
*/
private static final Map<String, HashAlgorithm[]> CUSTOM_ALGORITHMS = getCustomAlgorithmList();
/** Mock of a settings instance. */
private static NewSetting settings;
/** The datasource to test. */
private DataSource dataSource;
/** The DataSource method to test. */
private Method method;
/** Keeps track of the closeables which are created during the tested call. */
private List<AutoCloseable> closeables = new ArrayList<>();
/**
* Constructor for the test instance verifying the given method with the given hash algorithm.
*
* @param method The DataSource method to test
* @param name The name of the method
* @param algorithm The hash algorithm to use
*/
public AbstractResourceClosingTest(Method method, String name, HashAlgorithm algorithm) {
// Note ljacqu 20160227: The name parameter is necessary as we pass it from the @Parameters method;
// we use the method name in the annotation to name the test sensibly
this.method = method;
given(settings.getProperty(SecuritySettings.PASSWORD_HASH)).willReturn(algorithm);
}
/** Initialize the settings mock and makes it return the default of any given property by default. */
@BeforeClass
public static void initializeSettings() throws IOException, ClassNotFoundException {
settings = mock(NewSetting.class);
given(settings.getProperty(any(Property.class))).willAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocation) {
return ((Property) invocation.getArguments()[0]).getDefaultValue();
}
});
ConsoleLoggerTestInitializer.setupLogger();
}
/** Initialize the dataSource implementation to test based on a mock connection. */
@Before
public void setUpMockConnection() throws Exception {
Connection connection = initConnection();
dataSource = createDataSource(settings, connection);
}
/**
* The actual test -- executes the method given through the constructor and then verifies that all
* AutoCloseable mocks it constructed have been closed.
*/
@Test
public void shouldCloseResources() throws IllegalAccessException, InvocationTargetException {
method.invoke(dataSource, buildParamListForMethod(method));
verifyHaveMocksBeenClosed();
}
/**
* Initialization method -- provides the parameters to run the test with by scanning all DataSource
* methods. By default, we run one test per method with the default hash algorithm, XFBCRYPT.
* If the map of custom algorithms has an entry for the method name, we add an entry for each algorithm
* supplied by the map.
*
* @return Test parameters
*/
@Parameterized.Parameters(name = "{1}({2})")
public static Collection<Object[]> data() {
List<Method> methods = getDataSourceMethods();
List<Object[]> data = new ArrayList<>();
// Use XFBCRYPT if nothing else specified as there is a lot of specific behavior to this hash algorithm in MySQL
final HashAlgorithm[] defaultAlgorithm = new HashAlgorithm[]{HashAlgorithm.XFBCRYPT};
for (Method method : methods) {
HashAlgorithm[] algorithms = Objects.firstNonNull(CUSTOM_ALGORITHMS.get(method.getName()), defaultAlgorithm);
for (HashAlgorithm algorithm : algorithms) {
data.add(new Object[]{method, method.getName(), algorithm});
}
}
return data;
}
/* Create a DataSource instance with the given mock settings and mock connection. */
protected abstract DataSource createDataSource(NewSetting settings, Connection connection) throws Exception;
/* Get all methods of the DataSource interface, minus the ones in the ignored list. */
private static List<Method> getDataSourceMethods() {
List<Method> publicMethods = new ArrayList<>();
for (Method method : DataSource.class.getDeclaredMethods()) {
if (!IGNORED_METHODS.contains(method.getName())) {
publicMethods.add(method);
}
}
return publicMethods;
}
/**
* Verify that all AutoCloseables that have been created during the method execution have been closed.
*/
private void verifyHaveMocksBeenClosed() {
if (closeables.isEmpty()) {
System.out.println("Note: detected no AutoCloseables for method '" + method.getName() + "'");
}
try {
for (AutoCloseable autoCloseable : closeables) {
verify(autoCloseable).close();
}
} catch (Exception e) {
throw new IllegalStateException("Error verifying if autoCloseable was closed", e);
}
}
/**
* Helper method for building a list of test values to satisfy a method's signature.
*
* @param method The method to create a valid parameter list for
* @return Parameter list to invoke the given method with
*/
private static Object[] buildParamListForMethod(Method method) {
List<Object> params = new ArrayList<>();
int index = 0;
for (Class<?> paramType : method.getParameterTypes()) {
// Checking List.class == paramType instead of Class#isAssignableFrom means we really only accept List,
// but that is a sensible assumption and makes our life much easier later on when juggling with Type
Object param = (List.class == paramType)
? getTypedList(method.getGenericParameterTypes()[index])
: PARAM_VALUES.get(paramType);
Preconditions.checkNotNull(param, "No param type for " + paramType);
params.add(param);
++index;
}
return params.toArray();
}
/**
* Return a list with some test elements that correspond to the given list type's generic type.
*
* @param type The list type to process and build a test list for
* @return Test list with sample elements of the correct type
*/
private static List<?> getTypedList(Type type) {
if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) type;
Preconditions.checkArgument(List.class == parameterizedType.getRawType(), type + " should be a List");
Type genericType = parameterizedType.getActualTypeArguments()[0];
Object element = PARAM_VALUES.get(genericType);
Preconditions.checkNotNull(element, "No sample element for list of generic type " + genericType);
return Arrays.asList(element, element, element);
}
throw new IllegalStateException("Cannot build list for unexpected Type: " + type);
}
/* Initialize the map of test values to pass to methods to satisfy their signature. */
private static Map<Class<?>, Object> getDefaultParameters() {
HashedPassword hash = new HashedPassword("test", "test");
return ImmutableMap.<Class<?>, Object>builder()
.put(String.class, "test")
.put(int.class, 3)
.put(long.class, 102L)
.put(PlayerAuth.class, PlayerAuth.builder().name("test").realName("test").password(hash).build())
.put(HashedPassword.class, hash)
.build();
}
/**
* Return the custom list of hash algorithms to test a method with to execute code specific to
* one hash algorithm. By default, XFBCRYPT is used. Only MySQL has code specific to algorithms
* but for technical reasons the custom list will be used for all tested classes.
*
* @return List of custom algorithms by method
*/
private static Map<String, HashAlgorithm[]> getCustomAlgorithmList() {
// We use XFBCRYPT as default encryption method so we don't have to list many of the special cases for it
return ImmutableMap.<String, HashAlgorithm[]>builder()
.put("saveAuth", new HashAlgorithm[]{HashAlgorithm.PHPBB, HashAlgorithm.WORDPRESS})
.build();
}
// ---------------------
// Mock initialization
// ---------------------
/**
* Initialize the connection mock which produces additional AutoCloseable mocks and records them.
*
* @return Connection mock
*/
private Connection initConnection() {
Connection connection = mock(Connection.class);
try {
given(connection.prepareStatement(anyString())).willAnswer(preparedStatementAnswer());
given(connection.createStatement()).willAnswer(preparedStatementAnswer());
given(connection.createBlob()).willReturn(mock(Blob.class));
return connection;
} catch (SQLException e) {
throw new IllegalStateException("Could not initialize connection mock", e);
}
}
/* Create Answer that returns a PreparedStatement mock. */
private Answer<PreparedStatement> preparedStatementAnswer() {
return new Answer<PreparedStatement>() {
@Override
public PreparedStatement answer(InvocationOnMock invocation) throws SQLException {
PreparedStatement pst = mock(PreparedStatement.class);
closeables.add(pst);
given(pst.executeQuery()).willAnswer(resultSetAnswer());
given(pst.executeQuery(anyString())).willAnswer(resultSetAnswer());
return pst;
}
};
}
/* Create Answer that returns a ResultSet mock. */
private Answer<ResultSet> resultSetAnswer() throws SQLException {
return new Answer<ResultSet>() {
@Override
public ResultSet answer(InvocationOnMock invocation) throws Throwable {
ResultSet rs = initResultSet();
closeables.add(rs);
return rs;
}
};
}
/* Create a ResultSet mock. */
private ResultSet initResultSet() throws SQLException {
ResultSet rs = mock(ResultSet.class);
// Return true for ResultSet#next the first time to make sure we execute all code
given(rs.next()).willAnswer(new Answer<Boolean>() {
boolean isInitial = true;
@Override
public Boolean answer(InvocationOnMock invocation) {
if (isInitial) {
isInitial = false;
return true;
}
return false;
}
});
given(rs.getString(anyInt())).willReturn("test");
given(rs.getString(anyString())).willReturn("test");
Blob blob = mock(Blob.class);
given(blob.getBytes(anyLong(), anyInt())).willReturn(new byte[]{});
given(blob.length()).willReturn(0L);
given(rs.getBlob(anyInt())).willReturn(blob);
given(rs.getBlob(anyString())).willReturn(blob);
return rs;
}
}

View File

@ -0,0 +1,100 @@
package fr.xephi.authme.datasource;
import com.google.common.io.Files;
import fr.xephi.authme.TestHelper;
import fr.xephi.authme.cache.auth.PlayerAuth;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import static fr.xephi.authme.AuthMeMatchers.equalToHash;
import static fr.xephi.authme.AuthMeMatchers.hasAuthBasicData;
import static fr.xephi.authme.AuthMeMatchers.hasAuthLocation;
import static org.hamcrest.CoreMatchers.hasItem;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasSize;
import static org.junit.Assert.assertThat;
/**
* Integration test for the deprecated {@link FlatFile} datasource. The flatfile datasource is no longer used.
* Essentially, the only time we use it is in {@link fr.xephi.authme.converter.ForceFlatToSqlite},
* which requires {@link FlatFile#getAllAuths()}.
*/
public class FlatFileIntegrationTest {
@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
private DataSource dataSource;
@Before
public void copyFileToTemporaryFolder() throws IOException {
File originalFile = TestHelper.getJarFile("/datasource-integration/flatfile-test.txt");
File copy = temporaryFolder.newFile();
Files.copy(originalFile, copy);
dataSource = new FlatFile(copy);
}
@Test
public void shouldReturnIfAuthIsAvailableOrNot() {
// given / when
boolean isBobbyAvailable = dataSource.isAuthAvailable("bobby");
boolean isChrisAvailable = dataSource.isAuthAvailable("chris");
boolean isUserAvailable = dataSource.isAuthAvailable("USER");
// then
assertThat(isBobbyAvailable, equalTo(true));
assertThat(isChrisAvailable, equalTo(false));
assertThat(isUserAvailable, equalTo(true));
}
@Test
public void shouldReturnAllAuths() {
// given / when
List<PlayerAuth> authList = dataSource.getAllAuths();
// then
assertThat(authList, hasSize(7));
assertThat(getName("bobby", authList), hasAuthBasicData("bobby", "Bobby", "your@email.com", "123.45.67.89"));
assertThat(getName("bobby", authList), hasAuthLocation(1.05, 2.1, 4.2, "world"));
assertThat(getName("bobby", authList).getPassword(), equalToHash("$SHA$11aa0706173d7272$dbba966"));
assertThat(getName("twofields", authList), hasAuthBasicData("twofields", "twoFields", "your@email.com", "127.0.0.1"));
assertThat(getName("twofields", authList).getPassword(), equalToHash("hash1234"));
assertThat(getName("threefields", authList), hasAuthBasicData("threefields", "threeFields", "your@email.com", "33.33.33.33"));
assertThat(getName("fourfields", authList), hasAuthBasicData("fourfields", "fourFields", "your@email.com", "4.4.4.4"));
assertThat(getName("fourfields", authList).getLastLogin(), equalTo(404040404L));
assertThat(getName("sevenfields", authList), hasAuthLocation(7.7, 14.14, 21.21, "world"));
assertThat(getName("eightfields", authList), hasAuthLocation(8.8, 17.6, 26.4, "eightworld"));
assertThat(getName("eightfields", authList).getLastLogin(), equalTo(1234567888L));
assertThat(getName("eightfields", authList).getPassword(), equalToHash("hash8168"));
}
@Test
public void shouldAddAuth() {
// given / when
boolean response = dataSource.saveAuth(
PlayerAuth.builder().name("Test").email("user@EXAMPLE.org").ip("123.45.67.77").build());
List<PlayerAuth> authList = dataSource.getAllAuths();
// then
assertThat(response, equalTo(true));
assertThat(authList, hasSize(8));
assertThat(authList, hasItem(hasAuthBasicData("test", "test", "user@EXAMPLE.org", "123.45.67.77")));
}
private static PlayerAuth getName(String name, Collection<PlayerAuth> auths) {
for (PlayerAuth auth : auths) {
if (name.equals(auth.getNickname())) {
return auth;
}
}
throw new IllegalStateException("Did not find auth with name '" + name + "'");
}
}

View File

@ -0,0 +1,29 @@
package fr.xephi.authme.datasource;
import com.zaxxer.hikari.HikariDataSource;
import fr.xephi.authme.security.HashAlgorithm;
import fr.xephi.authme.settings.NewSetting;
import java.lang.reflect.Method;
import java.sql.Connection;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
/**
* Resource closing test for {@link MySQL}.
*/
public class MySqlResourceClosingTest extends AbstractResourceClosingTest {
public MySqlResourceClosingTest(Method method, String name, HashAlgorithm algorithm) {
super(method, name, algorithm);
}
@Override
protected DataSource createDataSource(NewSetting settings, Connection connection) throws Exception {
HikariDataSource hikariDataSource = mock(HikariDataSource.class);
given(hikariDataSource.getConnection()).willReturn(connection);
return new MySQL(settings, hikariDataSource);
}
}

View File

@ -0,0 +1,23 @@
package fr.xephi.authme.datasource;
import fr.xephi.authme.security.HashAlgorithm;
import fr.xephi.authme.settings.NewSetting;
import java.lang.reflect.Method;
import java.sql.Connection;
/**
* Resource closing test for {@link SQLite}.
*/
public class SQLiteResourceClosingTest extends AbstractResourceClosingTest {
public SQLiteResourceClosingTest(Method method, String name, HashAlgorithm algorithm) {
super(method, name, algorithm);
}
@Override
protected DataSource createDataSource(NewSetting settings, Connection connection) throws Exception {
return new SQLite(settings, connection);
}
}

View File

@ -1,14 +1,13 @@
package fr.xephi.authme.process.email; package fr.xephi.authme.process.email;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ConsoleLoggerTestInitializer; import fr.xephi.authme.ConsoleLoggerTestInitializer;
import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.cache.auth.PlayerCache; import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.output.Messages; import fr.xephi.authme.process.ProcessService;
import fr.xephi.authme.settings.NewSetting; import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.properties.RegistrationSettings;
import fr.xephi.authme.util.WrapperMock; import fr.xephi.authme.util.WrapperMock;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.junit.After; import org.junit.After;
@ -27,11 +26,10 @@ import static org.mockito.Mockito.when;
*/ */
public class AsyncAddEmailTest { public class AsyncAddEmailTest {
private Messages messages;
private Player player; private Player player;
private DataSource dataSource; private DataSource dataSource;
private PlayerCache playerCache; private PlayerCache playerCache;
private NewSetting settings; private ProcessService service;
@BeforeClass @BeforeClass
public static void setUp() { public static void setUp() {
@ -42,10 +40,10 @@ public class AsyncAddEmailTest {
// Clean up the fields to ensure that no test uses elements of another test // Clean up the fields to ensure that no test uses elements of another test
@After @After
public void removeFieldValues() { public void removeFieldValues() {
messages = null;
player = null; player = null;
dataSource = null; dataSource = null;
playerCache = null; playerCache = null;
service = null;
} }
@Test @Test
@ -61,11 +59,11 @@ public class AsyncAddEmailTest {
given(dataSource.updateEmail(any(PlayerAuth.class))).willReturn(true); given(dataSource.updateEmail(any(PlayerAuth.class))).willReturn(true);
// when // when
process.process(); process.run();
// then // then
verify(dataSource).updateEmail(auth); verify(dataSource).updateEmail(auth);
verify(messages).send(player, MessageKey.EMAIL_ADDED_SUCCESS); verify(service).send(player, MessageKey.EMAIL_ADDED_SUCCESS);
verify(auth).setEmail("my.mail@example.org"); verify(auth).setEmail("my.mail@example.org");
verify(playerCache).updatePlayer(auth); verify(playerCache).updatePlayer(auth);
} }
@ -83,11 +81,11 @@ public class AsyncAddEmailTest {
given(dataSource.updateEmail(any(PlayerAuth.class))).willReturn(false); given(dataSource.updateEmail(any(PlayerAuth.class))).willReturn(false);
// when // when
process.process(); process.run();
// then // then
verify(dataSource).updateEmail(auth); verify(dataSource).updateEmail(auth);
verify(messages).send(player, MessageKey.ERROR); verify(service).send(player, MessageKey.ERROR);
} }
@Test @Test
@ -102,10 +100,10 @@ public class AsyncAddEmailTest {
given(dataSource.isEmailStored("some.mail@example.org")).willReturn(false); given(dataSource.isEmailStored("some.mail@example.org")).willReturn(false);
// when // when
process.process(); process.run();
// then // then
verify(messages).send(player, MessageKey.USAGE_CHANGE_EMAIL); verify(service).send(player, MessageKey.USAGE_CHANGE_EMAIL);
verify(playerCache, never()).updatePlayer(any(PlayerAuth.class)); verify(playerCache, never()).updatePlayer(any(PlayerAuth.class));
} }
@ -121,10 +119,10 @@ public class AsyncAddEmailTest {
given(dataSource.isEmailStored("invalid_mail")).willReturn(false); given(dataSource.isEmailStored("invalid_mail")).willReturn(false);
// when // when
process.process(); process.run();
// then // then
verify(messages).send(player, MessageKey.INVALID_EMAIL); verify(service).send(player, MessageKey.INVALID_EMAIL);
verify(playerCache, never()).updatePlayer(any(PlayerAuth.class)); verify(playerCache, never()).updatePlayer(any(PlayerAuth.class));
} }
@ -140,10 +138,10 @@ public class AsyncAddEmailTest {
given(dataSource.isEmailStored("player@mail.tld")).willReturn(true); given(dataSource.isEmailStored("player@mail.tld")).willReturn(true);
// when // when
process.process(); process.run();
// then // then
verify(messages).send(player, MessageKey.EMAIL_ALREADY_USED_ERROR); verify(service).send(player, MessageKey.EMAIL_ALREADY_USED_ERROR);
verify(playerCache, never()).updatePlayer(any(PlayerAuth.class)); verify(playerCache, never()).updatePlayer(any(PlayerAuth.class));
} }
@ -156,10 +154,10 @@ public class AsyncAddEmailTest {
given(dataSource.isAuthAvailable("Username12")).willReturn(true); given(dataSource.isAuthAvailable("Username12")).willReturn(true);
// when // when
process.process(); process.run();
// then // then
verify(messages).send(player, MessageKey.LOGIN_MESSAGE); verify(service).send(player, MessageKey.LOGIN_MESSAGE);
verify(playerCache, never()).updatePlayer(any(PlayerAuth.class)); verify(playerCache, never()).updatePlayer(any(PlayerAuth.class));
} }
@ -170,13 +168,13 @@ public class AsyncAddEmailTest {
given(player.getName()).willReturn("user"); given(player.getName()).willReturn("user");
given(playerCache.isAuthenticated("user")).willReturn(false); given(playerCache.isAuthenticated("user")).willReturn(false);
given(dataSource.isAuthAvailable("user")).willReturn(false); given(dataSource.isAuthAvailable("user")).willReturn(false);
Settings.emailRegistration = true; given(service.getProperty(RegistrationSettings.USE_EMAIL_REGISTRATION)).willReturn(true);
// when // when
process.process(); process.run();
// then // then
verify(messages).send(player, MessageKey.REGISTER_EMAIL_MESSAGE); verify(service).send(player, MessageKey.REGISTER_EMAIL_MESSAGE);
verify(playerCache, never()).updatePlayer(any(PlayerAuth.class)); verify(playerCache, never()).updatePlayer(any(PlayerAuth.class));
} }
@ -187,13 +185,13 @@ public class AsyncAddEmailTest {
given(player.getName()).willReturn("user"); given(player.getName()).willReturn("user");
given(playerCache.isAuthenticated("user")).willReturn(false); given(playerCache.isAuthenticated("user")).willReturn(false);
given(dataSource.isAuthAvailable("user")).willReturn(false); given(dataSource.isAuthAvailable("user")).willReturn(false);
Settings.emailRegistration = false; given(service.getProperty(RegistrationSettings.USE_EMAIL_REGISTRATION)).willReturn(false);
// when // when
process.process(); process.run();
// then // then
verify(messages).send(player, MessageKey.REGISTER_MESSAGE); verify(service).send(player, MessageKey.REGISTER_MESSAGE);
verify(playerCache, never()).updatePlayer(any(PlayerAuth.class)); verify(playerCache, never()).updatePlayer(any(PlayerAuth.class));
} }
@ -204,14 +202,12 @@ public class AsyncAddEmailTest {
* @return The created process * @return The created process
*/ */
private AsyncAddEmail createProcess(String email) { private AsyncAddEmail createProcess(String email) {
messages = mock(Messages.class);
AuthMe authMe = mock(AuthMe.class);
when(authMe.getMessages()).thenReturn(messages);
player = mock(Player.class); player = mock(Player.class);
dataSource = mock(DataSource.class); dataSource = mock(DataSource.class);
playerCache = mock(PlayerCache.class); playerCache = mock(PlayerCache.class);
settings = mock(NewSetting.class); service = mock(ProcessService.class);
return new AsyncAddEmail(player, authMe, email, dataSource, playerCache, settings); when(service.getSettings()).thenReturn(mock(NewSetting.class));
return new AsyncAddEmail(player, email, dataSource, playerCache, service);
} }
} }

View File

@ -0,0 +1,7 @@
Bobby:$SHA$11aa0706173d7272$dbba966:123.45.67.89:1449136800:1.05:2.1:4.2:world:your@email.com
user:b28c32f624a4eb161d6adc9acb5bfc5b:34.56.78.90:1453242857:124.1:76.3:-127.8:nether:user@example.org
twoFields:hash1234
threeFields:hash369:33.33.33.33
fourFields:$hash$4444:4.4.4.4:404040404
sevenFields:hash7749:5.5.5.55:1414141414:7.7:14.14:21.21
eightFields:hash8168:6.6.6.66:1234567888:8.8:17.6:26.4:eightworld