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!"
<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>
<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>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- 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>
<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>
<buildNumber>Unknown</buildNumber>
<!-- Change Compiler Version (JDK) HERE! -->
<javaVersion>1.7</javaVersion>
<!-- Change Bukkit Version HERE! -->
<bukkitVersion>1.9-pre1-SNAPSHOT</bukkitVersion>
<bukkitVersion>1.9-SNAPSHOT</bukkitVersion>
</properties>
<!-- Jenkins profile (add the real buildNumber to the version string) -->
<profiles>
<profile>
<id>jenkins</id>
@ -84,33 +87,21 @@
<testSourceDirectory>src/test/java</testSourceDirectory>
<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>
<targetPath>.</targetPath>
<filtering>false</filtering>
<directory>.</directory>
<includes>
<include>LICENSE</include>
</includes>
</resource>
<resource>
<targetPath>.</targetPath>
<filtering>true</filtering>
<directory>src/main/resources/</directory>
<includes>
<include>*.yml</include>
<include>*</include>
</includes>
<excludes>
<exclude>plugin.yml</exclude>
</excludes>
</resource>
<resource>
<targetPath>./messages/</targetPath>
@ -128,15 +119,28 @@
</testResources>
<plugins>
<!-- Maven Java Compiler -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.7</source>
<target>${javaVersion}</target>
<source>${jdkVersion}</source>
<target>${jdkVersion}</target>
<testSource>${testJreVersion}</testSource>
<testTarget>${testJreVersion}</testTarget>
</configuration>
</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>
<!--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)-->
@ -161,33 +165,11 @@
</excludes>
</artifactSet>
<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>
<pattern>com.google.gson</pattern>
<shadedPattern>fr.xephi.authme.libs.google</shadedPattern>
</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>
<pattern>com.zaxxer.hikari</pattern>
<shadedPattern>fr.xephi.authme.libs.hikari</shadedPattern>
@ -204,6 +186,11 @@
<pattern>net.ricecode.similarity</pattern>
<shadedPattern>fr.xephi.authme.libs.similarity</shadedPattern>
</relocation>
<!-- MCStats.org metrics -->
<relocation>
<pattern>org.mcstats</pattern>
<shadedPattern>fr.xephi.authme</shadedPattern>
</relocation>
</relocations>
<outputFile>target/${jarName}-spigot.jar</outputFile>
</configuration>
@ -215,34 +202,12 @@
<goal>shade</goal>
</goals>
<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>
<relocation>
<pattern>com.google</pattern>
<shadedPattern>fr.xephi.authme.libs.google</shadedPattern>
</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>
<pattern>com.zaxxer.hikari</pattern>
<shadedPattern>fr.xephi.authme.libs.hikari</shadedPattern>
@ -259,16 +224,22 @@
<pattern>net.ricecode.similarity</pattern>
<shadedPattern>fr.xephi.authme.libs.similarity</shadedPattern>
</relocation>
<!-- MCStats.org metrics -->
<relocation>
<pattern>org.mcstats</pattern>
<shadedPattern>fr.xephi.authme</shadedPattern>
</relocation>
</relocations>
<outputFile>target/${jarName}-legacy.jar</outputFile>
</configuration>
</execution>
</executions>
</plugin>
<!-- Test coverage -->
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.5.201505241946</version>
<version>0.7.6.201602180812</version>
<executions>
<execution>
<id>prepare-agent</id>
@ -278,11 +249,12 @@
</execution>
</executions>
</plugin>
<!-- Coveralls data -->
<plugin>
<groupId>org.eluder.coveralls</groupId>
<artifactId>coveralls-maven-plugin</artifactId>
<version>4.1.0</version>
<!-- Token is provided by mvn command -->
<!-- The secret token is provided by console! -->
</plugin>
<!-- Javadocs settings -->
<plugin>
@ -292,7 +264,10 @@
<configuration>
<charset>UTF-8</charset>
<docencoding>UTF-8</docencoding>
<dependencyLocationsEnabled>false</dependencyLocationsEnabled>
<docfilessubdirs>true</docfilessubdirs>
<show>public</show>
<failOnError>false</failOnError>
</configuration>
</plugin>
</plugins>
@ -305,10 +280,10 @@
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots</url>
</repository>
<!-- EssentialsX Repo -->
<!-- Essentials Repo -->
<repository>
<id>ess-repo</id>
<url>http://ci.drtshock.net/plugin/repository/everything</url>
<url>http://repo.ess3.net/content/groups/essentials</url>
</repository>
<!-- CombatTagPlus Repo -->
@ -359,7 +334,7 @@
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>2.4.3</version>
<version>2.4.5-SNAPSHOT</version>
<scope>compile</scope>
<exclusions>
<exclusion>
@ -372,7 +347,7 @@
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
<version>1.7.16</version>
<version>1.7.18</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
@ -413,7 +388,7 @@
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.6.1</version>
<version>2.6.2</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
@ -664,16 +639,20 @@
<optional>true</optional>
</dependency>
<!-- EssentialsX plugin, http://www.spigotmc.org/resources/essentialsx.9089/ -->
<!-- Essentials plugin -->
<dependency>
<groupId>net.ess3</groupId>
<artifactId>EssentialsX</artifactId>
<version>2.0.1-SNAPSHOT</version>
<artifactId>Essentials</artifactId>
<version>2.13-SNAPSHOT</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
</exclusion>
<exclusion>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
</exclusion>
</exclusions>
<optional>true</optional>
@ -683,7 +662,7 @@
<dependency>
<groupId>net.minelink</groupId>
<artifactId>CombatTagPlus</artifactId>
<version>1.2.1-SNAPSHOT</version>
<version>1.2.2-SNAPSHOT</version>
<scope>provided</scope>
<exclusions>
<exclusion>

View File

@ -42,14 +42,15 @@ import fr.xephi.authme.output.Messages;
import fr.xephi.authme.permission.PermissionsManager;
import fr.xephi.authme.permission.PlayerStatePermission;
import fr.xephi.authme.process.Management;
import fr.xephi.authme.process.ProcessService;
import fr.xephi.authme.security.PasswordSecurity;
import fr.xephi.authme.security.crypts.SHA256;
import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.OtherAccounts;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.SettingsMigrationService;
import fr.xephi.authme.settings.Spawn;
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.PluginSettings;
import fr.xephi.authme.settings.properties.RestrictionSettings;
@ -64,7 +65,6 @@ import org.apache.logging.log4j.LogManager;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Server;
import org.bukkit.World;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@ -76,6 +76,7 @@ import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
@ -104,15 +105,14 @@ public class AuthMe extends JavaPlugin {
// Private Instances
private static AuthMe plugin;
private static Server server;
private Management management;
private CommandHandler commandHandler = null;
private PermissionsManager permsMan = null;
private NewSetting newSettings;
private Messages messages;
private JsonCache playerBackup;
private PasswordSecurity passwordSecurity;
private DataSource database;
/*
* Maps and stuff
* TODO: Clean up and Move into a manager
*/
public final ConcurrentHashMap<String, BukkitTask> sessions = new ConcurrentHashMap<>();
public final ConcurrentHashMap<String, Integer> captcha = new ConcurrentHashMap<>();
public final ConcurrentHashMap<String, String> cap = new ConcurrentHashMap<>();
public final ConcurrentHashMap<String, String> realIp = new ConcurrentHashMap<>();
/*
* Public Instances
* TODO #432: Encapsulation
@ -120,9 +120,7 @@ public class AuthMe extends JavaPlugin {
public NewAPI api;
public SendMailSSL mail;
public DataManager dataManager;
public OtherAccounts otherAccounts;
public Location essentialsSpawn;
/*
* Plugin Hooks
* TODO: Move into modules
@ -133,15 +131,14 @@ public class AuthMe extends JavaPlugin {
public AuthMeInventoryPacketAdapter inventoryProtector;
public AuthMeTabCompletePacketAdapter tabComplete;
public AuthMeTablistPacketAdapter tablistHider;
/*
* Maps and stuff
* TODO: Clean up and Move into a manager
*/
public final ConcurrentHashMap<String, BukkitTask> sessions = new ConcurrentHashMap<>();
public final ConcurrentHashMap<String, Integer> captcha = new ConcurrentHashMap<>();
public final ConcurrentHashMap<String, String> cap = new ConcurrentHashMap<>();
public final ConcurrentHashMap<String, String> realIp = new ConcurrentHashMap<>();
private Management management;
private CommandHandler commandHandler = null;
private PermissionsManager permsMan = null;
private NewSetting newSettings;
private Messages messages;
private JsonCache playerBackup;
private PasswordSecurity passwordSecurity;
private DataSource database;
/**
* Get the plugin's instance.
@ -259,9 +256,6 @@ public class AuthMe extends JavaPlugin {
permsMan = initializePermissionsManager();
commandHandler = initializeCommandHandler(permsMan, messages, passwordSecurity, newSettings);
// Setup otherAccounts file
this.otherAccounts = OtherAccounts.getInstance();
// Set up Metrics
MetricsStarter.setupMetrics(plugin, newSettings);
@ -306,7 +300,8 @@ public class AuthMe extends JavaPlugin {
setupApi();
// 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
setupBungeeCordHook();
@ -494,11 +489,41 @@ public class AuthMe extends JavaPlugin {
if (newSettings != null) {
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
if (database != null) {
database.close();
}
// Disabled correctly
ConsoleLogger.info("AuthMe " + this.getDescription().getVersion() + " disabled!");
@ -518,7 +543,10 @@ public class AuthMe extends JavaPlugin {
* Sets up the data source.
*
* @param settings The settings instance
*
* @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 {
if (this.database != null) {
@ -653,6 +681,7 @@ public class AuthMe extends JavaPlugin {
ConsoleLogger.showError("WARNING! The protectInventory feature requires ProtocolLib! Disabling it...");
Settings.protectInventoryBeforeLogInEnabled = false;
newSettings.setProperty(RestrictionSettings.PROTECT_INVENTORY_BEFORE_LOGIN, false);
newSettings.save();
}
return;
}
@ -667,14 +696,14 @@ public class AuthMe extends JavaPlugin {
if (newSettings.getProperty(RestrictionSettings.DENY_TABCOMPLETE_BEFORE_LOGIN) && tabComplete == null) {
tabComplete = new AuthMeTabCompletePacketAdapter(this);
tabComplete.register();
} else if (inventoryProtector != null) {
} else if (tabComplete != null) {
tabComplete.unregister();
tabComplete = null;
}
if (newSettings.getProperty(RestrictionSettings.HIDE_TABLIST_BEFORE_LOGIN) && tablistHider == null) {
tablistHider = new AuthMeTablistPacketAdapter(this);
tablistHider.register();
} else if (inventoryProtector != null) {
} else if (tablistHider != null) {
tablistHider.unregister();
tablistHider = null;
}
@ -748,42 +777,6 @@ public class AuthMe extends JavaPlugin {
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() {
if (!newSettings.getProperty(RECALL_PLAYERS)) {
return;
@ -793,7 +786,7 @@ public class AuthMe extends JavaPlugin {
public void run() {
for (PlayerAuth auth : database.getLoggedPlayers()) {
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());
if (player != null) {
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) {
@ -863,15 +856,6 @@ public class AuthMe extends JavaPlugin {
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.
*

View File

@ -13,7 +13,10 @@ import fr.xephi.authme.security.crypts.HashedPassword;
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 {
@ -23,7 +26,7 @@ public class NewAPI {
/**
* Constructor for NewAPI.
*
* @param plugin AuthMe
* @param plugin The AuthMe plugin instance
*/
public NewAPI(AuthMe plugin) {
this.plugin = plugin;
@ -32,16 +35,17 @@ public class NewAPI {
/**
* Constructor for NewAPI.
*
* @param server Server
* @param server The server instance
*/
public NewAPI(Server server) {
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() {
if (singleton != null) {
@ -69,7 +73,6 @@ public class NewAPI {
* Return whether the given player is authenticated.
*
* @param player The player to verify
*
* @return true if the player is authenticated
*/
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) {
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
* @see fr.xephi.authme.settings.properties.RestrictionSettings#UNRESTRICTED_NAMES
*/
public boolean isUnrestricted(Player player) {
return Utils.isUnrestricted(player);
@ -97,30 +104,21 @@ public class NewAPI {
/**
* 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
*/
public Location getLastLocation(Player player) {
try {
PlayerAuth auth = PlayerCache.getInstance().getAuth(player.getName());
if (auth != null) {
return new Location(Bukkit.getWorld(auth.getWorld()), auth.getQuitLocX(), auth.getQuitLocY(), auth.getQuitLocZ());
} else {
return null;
}
} catch (NullPointerException ex) {
return null;
PlayerAuth auth = PlayerCache.getInstance().getAuth(player.getName());
if (auth != null) {
return new Location(Bukkit.getWorld(auth.getWorld()), auth.getQuitLocX(), auth.getQuitLocY(), auth.getQuitLocZ());
}
return null;
}
/**
* Return whether the player is registered.
*
* @param playerName The player name to check
*
* @return true if player is registered, false otherwise
*/
public boolean isRegistered(String playerName) {
@ -133,7 +131,6 @@ public class NewAPI {
*
* @param playerName The player to check the password for
* @param passwordToCheck The password to check
*
* @return true if the password is correct, false otherwise
*/
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 password The password to register the player with
*
* @return true if the player was registered successfully
*/
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
*/
@ -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 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
*/

View File

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

View File

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

View File

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

View File

@ -1,14 +1,5 @@
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.ConsoleLogger;
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.TimeoutTask;
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.
@ -55,19 +54,20 @@ public class UnregisterAdminCommand implements ExecutableCommand {
if (target != null && target.isOnline()) {
Utils.teleportToSpawn(target);
LimboCache.getInstance().addLimboPlayer(target);
int delay = Settings.getRegistrationTimeout * 20;
int timeOut = Settings.getRegistrationTimeout * 20;
int interval = Settings.getWarnMessageInterval;
BukkitScheduler scheduler = sender.getServer().getScheduler();
if (delay != 0) {
BukkitTask id = scheduler.runTaskLaterAsynchronously(plugin, new TimeoutTask(plugin, playerNameLowerCase, target), delay);
if (timeOut != 0) {
BukkitTask id = scheduler.runTaskLater(plugin, new TimeoutTask(plugin, playerNameLowerCase, target), timeOut);
LimboCache.getInstance().getLimboPlayer(playerNameLowerCase).setTimeoutTaskId(id);
}
LimboCache.getInstance().getLimboPlayer(playerNameLowerCase).setMessageTaskId(
scheduler.runTaskAsynchronously(plugin,
new MessageTask(plugin, playerNameLowerCase, commandService.retrieveMessage(MessageKey.REGISTER_MESSAGE), interval)));
scheduler.runTask(
plugin, new MessageTask(plugin, playerNameLowerCase, MessageKey.REGISTER_MESSAGE, interval)
)
);
if (Settings.applyBlindEffect) {
target.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS,
Settings.getRegistrationTimeout * 20, 2));
target.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, timeOut, 2));
}
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.command.CommandService;
import fr.xephi.authme.command.ExecutableCommand;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import static fr.xephi.authme.settings.properties.PluginSettings.HELP_HEADER;
import fr.xephi.authme.util.Utils;
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 {
@ -73,7 +73,7 @@ public class VersionCommand implements ExecutableCommand {
private static boolean isPlayerOnline(String minecraftName) {
// 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.
for (Player player : Bukkit.getOnlinePlayers()) {
for (Player player : Utils.getOnlinePlayers()) {
if (player.getName().equalsIgnoreCase(minecraftName)) {
return true;
}

View File

@ -3,39 +3,51 @@ package fr.xephi.authme.converter;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.datasource.DataSourceType;
import fr.xephi.authme.datasource.SQLite;
import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.properties.DatabaseSettings;
import java.sql.SQLException;
import fr.xephi.authme.datasource.FlatFile;
import fr.xephi.authme.util.StringUtils;
import java.util.ArrayList;
import java.util.List;
/**
* Mandatory migration from the deprecated flat file datasource to SQLite.
*/
public class ForceFlatToSqlite {
public class ForceFlatToSqlite implements Converter {
private final DataSource database;
private final NewSetting settings;
private final DataSource source;
private final DataSource destination;
public ForceFlatToSqlite(DataSource database, NewSetting settings) {
this.database = database;
this.settings = settings;
/**
* Constructor.
*
* @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 {
DataSource sqlite = new SQLite(settings);
for (PlayerAuth auth : database.getAllAuths()) {
auth.setRealName("Player");
sqlite.saveAuth(auth);
/**
* Perform the conversion.
*/
@Override
public void run() {
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.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.cache.RemovalListener;
import com.google.common.cache.RemovalNotification;
import com.google.common.util.concurrent.ListenableFuture;
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.PlayerCache;
import fr.xephi.authme.security.crypts.HashedPassword;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
@ -20,6 +25,7 @@ public class CacheDataSource implements DataSource {
private final DataSource source;
private final LoadingCache<String, Optional<PlayerAuth>> cachedAuths;
private final ListeningExecutorService executorService;
/**
* Constructor for CacheDataSource.
@ -27,25 +33,35 @@ public class CacheDataSource implements DataSource {
* @param src DataSource
*/
public CacheDataSource(DataSource src) {
this.source = src;
this.cachedAuths = CacheBuilder.newBuilder()
.expireAfterWrite(8, TimeUnit.MINUTES)
.removalListener(new RemovalListener<String, Optional<PlayerAuth>>() {
source = src;
executorService = MoreExecutors.listeningDecorator(
Executors.newCachedThreadPool(new ThreadFactoryBuilder()
.setDaemon(true)
.setNameFormat("AuthMe-CacheLoader")
.build())
);
cachedAuths = CacheBuilder.newBuilder()
.refreshAfterWrite(8, TimeUnit.MINUTES)
.build(new CacheLoader<String, Optional<PlayerAuth>>() {
@Override
public void onRemoval(RemovalNotification<String, Optional<PlayerAuth>> removalNotification) {
String name = removalNotification.getKey();
if (PlayerCache.getInstance().isAuthenticated(name)) {
cachedAuths.getUnchecked(name);
}
public Optional<PlayerAuth> load(String key) {
return Optional.fromNullable(source.getAuth(key));
}
})
.build(
new CacheLoader<String, Optional<PlayerAuth>>() {
@Override
public Optional<PlayerAuth> load(String key) {
return Optional.fromNullable(source.getAuth(key));
}
});
@Override
public ListenableFuture<Optional<PlayerAuth>> reload(final String key, Optional<PlayerAuth> oldValue) {
return executorService.submit(new Callable<Optional<PlayerAuth>>() {
@Override
public Optional<PlayerAuth> call() {
return load(key);
}
});
}
});
}
public LoadingCache<String, Optional<PlayerAuth>> getCachedAuths() {
return cachedAuths;
}
@Override
@ -137,6 +153,13 @@ public class CacheDataSource implements DataSource {
@Override
public synchronized void close() {
source.close();
cachedAuths.invalidateAll();
executorService.shutdown();
try {
executorService.awaitTermination(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
ConsoleLogger.writeStackTrace(e);
}
}
@Override
@ -201,12 +224,6 @@ public class CacheDataSource implements DataSource {
return source.getAccountsRegistered();
}
@Override
public void updateName(final String oldOne, final String newOne) { // unused method
source.updateName(oldOne, newOne);
cachedAuths.invalidate(oldOne);
}
@Override
public boolean updateRealName(String user, String realName) {
boolean result = source.updateRealName(user, realName);

View File

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

View File

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

View File

@ -1,5 +1,6 @@
package fr.xephi.authme.datasource;
import com.google.common.annotations.VisibleForTesting;
import com.zaxxer.hikari.HikariDataSource;
import com.zaxxer.hikari.pool.HikariPool.PoolInitializationException;
import fr.xephi.authme.AuthMe;
@ -41,6 +42,10 @@ public class MySQL implements DataSource {
private final HashAlgorithm hashAlgorithm;
private HikariDataSource ds;
private final String phpBbPrefix;
private final int phpBbGroup;
private final String wordpressPrefix;
public MySQL(NewSetting settings) throws ClassNotFoundException, SQLException, PoolInitializationException {
this.host = settings.getProperty(DatabaseSettings.MYSQL_HOST);
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.col = new Columns(settings);
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)
try {
@ -81,6 +89,7 @@ public class MySQL implements DataSource {
}
}
@VisibleForTesting
MySQL(NewSetting settings, HikariDataSource hikariDataSource) {
this.host = settings.getProperty(DatabaseSettings.MYSQL_HOST);
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.col = new Columns(settings);
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;
}
@ -359,10 +371,10 @@ public class MySQL implements DataSource {
if (rs.next()) {
int id = rs.getInt(col.ID);
// 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 (?,?,?,?);";
pst2 = con.prepareStatement(sql);
pst2.setInt(1, Settings.getPhpbbGroup);
pst2.setInt(1, phpBbGroup);
pst2.setInt(2, id);
pst2.setInt(3, 0);
pst2.setInt(4, 0);
@ -380,7 +392,7 @@ public class MySQL implements DataSource {
sql = "UPDATE " + tableName + " SET " + tableName
+ ".group_id=? WHERE " + col.NAME + "=?;";
pst2 = con.prepareStatement(sql);
pst2.setInt(1, Settings.getPhpbbGroup);
pst2.setInt(1, phpBbGroup);
pst2.setString(2, auth.getNickname());
pst2.executeUpdate();
pst2.close();
@ -403,7 +415,7 @@ public class MySQL implements DataSource {
pst2.executeUpdate();
pst2.close();
// Increment num_users
sql = "UPDATE " + Settings.getPhpbbPrefix
sql = "UPDATE " + phpBbPrefix
+ "config SET config_value = config_value + 1 WHERE config_name = 'num_users';";
pst2 = con.prepareStatement(sql);
pst2.executeUpdate();
@ -417,7 +429,7 @@ public class MySQL implements DataSource {
rs = pst.executeQuery();
if (rs.next()) {
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);
// First Name
pst2.setInt(1, id);
@ -620,31 +632,32 @@ public class MySQL implements DataSource {
@Override
public synchronized boolean removeAuth(String user) {
user = user.toLowerCase();
try (Connection con = getConnection()) {
String sql;
PreparedStatement pst;
String sql = "DELETE FROM " + tableName + " WHERE " + col.NAME + "=?;";
PreparedStatement xfSelect = null;
PreparedStatement xfDelete = null;
try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
if (hashAlgorithm == HashAlgorithm.XFBCRYPT) {
sql = "SELECT " + col.ID + " FROM " + tableName + " WHERE " + col.NAME + "=?;";
pst = con.prepareStatement(sql);
pst.setString(1, user);
ResultSet rs = pst.executeQuery();
if (rs.next()) {
int id = rs.getInt(col.ID);
sql = "DELETE FROM xf_user_authenticate WHERE " + col.ID + "=?;";
PreparedStatement st = con.prepareStatement(sql);
st.setInt(1, id);
st.executeUpdate();
st.close();
xfSelect = con.prepareStatement(sql);
xfSelect.setString(1, user);
try (ResultSet rs = xfSelect.executeQuery()) {
if (rs.next()) {
int id = rs.getInt(col.ID);
sql = "DELETE FROM xf_user_authenticate WHERE " + col.ID + "=?;";
xfDelete = con.prepareStatement(sql);
xfDelete.setInt(1, id);
xfDelete.executeUpdate();
}
}
rs.close();
pst.close();
}
pst = con.prepareStatement("DELETE FROM " + tableName + " WHERE " + col.NAME + "=?;");
pst.setString(1, user);
pst.executeUpdate();
return true;
} catch (SQLException ex) {
logSqlException(ex);
} finally {
close(xfSelect);
close(xfDelete);
}
return false;
}
@ -817,18 +830,6 @@ public class MySQL implements DataSource {
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
public boolean updateRealName(String user, String realName) {
String sql = "UPDATE " + tableName + " SET " + col.REAL_NAME + "=? WHERE " + col.NAME + "=?;";
@ -891,22 +892,24 @@ public class MySQL implements DataSource {
@Override
public List<PlayerAuth> getLoggedPlayers() {
List<PlayerAuth> auths = new ArrayList<>();
try (Connection con = getConnection()) {
Statement st = con.createStatement();
ResultSet rs = st.executeQuery("SELECT * FROM " + tableName + " WHERE " + col.IS_LOGGED + "=1;");
PreparedStatement pst = con.prepareStatement("SELECT data FROM xf_user_authenticate WHERE " + col.ID + "=?;");
String sql = "SELECT * FROM " + tableName + " WHERE " + col.IS_LOGGED + "=1;";
try (Connection con = getConnection();
Statement st = con.createStatement();
ResultSet rs = st.executeQuery(sql)) {
while (rs.next()) {
PlayerAuth pAuth = buildAuthFromResultSet(rs);
if (hashAlgorithm == HashAlgorithm.XFBCRYPT) {
int id = rs.getInt(col.ID);
pst.setInt(1, id);
ResultSet rs2 = pst.executeQuery();
if (rs2.next()) {
Blob blob = rs2.getBlob("data");
byte[] bytes = blob.getBytes(1, (int) blob.length());
pAuth.setPassword(new HashedPassword(XFBCRYPT.getHashFromBlob(bytes)));
try (PreparedStatement pst = con.prepareStatement("SELECT data FROM xf_user_authenticate WHERE " + col.ID + "=?;")) {
int id = rs.getInt(col.ID);
pst.setInt(1, id);
ResultSet rs2 = pst.executeQuery();
if (rs2.next()) {
Blob blob = rs2.getBlob("data");
byte[] bytes = blob.getBytes(1, (int) blob.length());
pAuth.setPassword(new HashedPassword(XFBCRYPT.getHashFromBlob(bytes)));
}
rs2.close();
}
rs2.close();
}
auths.add(pAuth);
}
@ -990,12 +993,22 @@ public class MySQL implements DataSource {
}
private static void close(ResultSet rs) {
if (rs != null) {
try {
try {
if (rs != null && !rs.isClosed()) {
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.
*
* @throws ClassNotFoundException Exception
* @throws SQLException Exception
* @param settings The settings instance
* @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 {
this.database = settings.getProperty(DatabaseSettings.MYSQL_DATABASE);
@ -350,8 +351,9 @@ public class SQLite implements DataSource {
@Override
public synchronized void close() {
try {
if (con != null && !con.isClosed())
con.close();
if (con != null && !con.isClosed()) {
con.close();
}
} catch (SQLException ex) {
logSqlException(ex);
}
@ -421,17 +423,14 @@ public class SQLite implements DataSource {
@Override
public void purgeBanned(List<String> banned) {
PreparedStatement pst = null;
try {
String sql = "DELETE FROM " + tableName + " WHERE " + col.NAME + "=?;";
try (PreparedStatement pst = con.prepareStatement(sql)) {
for (String name : banned) {
pst = con.prepareStatement("DELETE FROM " + tableName + " WHERE " + col.NAME + "=?;");
pst.setString(1, name);
pst.executeUpdate();
}
} catch (SQLException ex) {
logSqlException(ex);
} finally {
close(pst);
}
}
@ -507,37 +506,17 @@ public class SQLite implements DataSource {
@Override
public int getAccountsRegistered() {
PreparedStatement pst = null;
ResultSet rs;
try {
pst = con.prepareStatement("SELECT COUNT(*) FROM " + tableName + ";");
rs = pst.executeQuery();
if (rs != null && rs.next()) {
String sql = "SELECT COUNT(*) FROM " + tableName + ";";
try (PreparedStatement pst = con.prepareStatement(sql); ResultSet rs = pst.executeQuery()) {
if (rs.next()) {
return rs.getInt(1);
}
} catch (SQLException ex) {
logSqlException(ex);
} finally {
close(pst);
}
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
public boolean updateRealName(String user, String realName) {
String sql = "UPDATE " + tableName + " SET " + col.REAL_NAME + "=? WHERE " + col.NAME + "=?;";
@ -569,19 +548,14 @@ public class SQLite implements DataSource {
@Override
public List<PlayerAuth> getAllAuths() {
List<PlayerAuth> auths = new ArrayList<>();
PreparedStatement pst = null;
ResultSet rs;
try {
pst = con.prepareStatement("SELECT * FROM " + tableName + ";");
rs = pst.executeQuery();
String sql = "SELECT * FROM " + tableName + ";";
try (PreparedStatement pst = con.prepareStatement(sql); ResultSet rs = pst.executeQuery()) {
while (rs.next()) {
PlayerAuth auth = buildAuthFromResultSet(rs);
auths.add(auth);
}
} catch (SQLException ex) {
logSqlException(ex);
} finally {
close(pst);
}
return auths;
}
@ -589,19 +563,14 @@ public class SQLite implements DataSource {
@Override
public List<PlayerAuth> getLoggedPlayers() {
List<PlayerAuth> auths = new ArrayList<>();
PreparedStatement pst = null;
ResultSet rs;
try {
pst = con.prepareStatement("SELECT * FROM " + tableName + " WHERE " + col.IS_LOGGED + "=1;");
rs = pst.executeQuery();
String sql = "SELECT * FROM " + tableName + " WHERE " + col.IS_LOGGED + "=1;";
try (PreparedStatement pst = con.prepareStatement(sql); ResultSet rs = pst.executeQuery()) {
while (rs.next()) {
PlayerAuth auth = buildAuthFromResultSet(rs);
auths.add(auth);
}
} catch (SQLException ex) {
logSqlException(ex);
} finally {
close(pst);
}
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.
* {@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 {

View File

@ -41,7 +41,7 @@ public enum MessageKey {
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"),

View File

@ -96,6 +96,7 @@ public class Messages {
*
* @param key The key of the message to send
* @param replacements The replacements to apply for the tags
* @return The message from the file with replacements
*/
public String retrieveSingle(MessageKey key, String... replacements) {
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
*/

View File

@ -2,6 +2,7 @@ package fr.xephi.authme.process;
import fr.xephi.authme.AuthMe;
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.AsyncChangeEmail;
import fr.xephi.authme.process.join.AsynchronousJoin;
@ -20,18 +21,25 @@ public class Management {
private final AuthMe plugin;
private final BukkitScheduler sched;
private final ProcessService processService;
private final DataSource dataSource;
private final PlayerCache playerCache;
private final NewSetting settings;
/**
* Constructor for Management.
*
* @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.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) {
@ -39,7 +47,7 @@ public class Management {
@Override
public void run() {
new AsynchronousLogin(player, password, forceLogin, plugin, plugin.getDataSource(), settings)
new AsynchronousLogin(player, password, forceLogin, plugin, dataSource, settings)
.process();
}
});
@ -60,7 +68,7 @@ public class Management {
@Override
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) {
sched.runTaskAsynchronously(plugin, new Runnable() {
@Override
public void run() {
new AsynchronousJoin(player, plugin, plugin.getDataSource()).process();
}
});
runTask(new AsynchronousJoin(player, plugin, dataSource, playerCache, processService));
}
public void performQuit(final Player player, final boolean isKick) {
@ -91,28 +92,26 @@ public class Management {
@Override
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) {
sched.runTaskAsynchronously(plugin, new Runnable() {
@Override
public void run() {
new AsyncAddEmail(player, plugin, newEmail, plugin.getDataSource(),
PlayerCache.getInstance(), settings).process();
}
});
runTask(new AsyncAddEmail(player, newEmail, dataSource, playerCache, processService));
}
public void performChangeEmail(final Player player, final String oldEmail, final String newEmail) {
sched.runTaskAsynchronously(plugin, new Runnable() {
@Override
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;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.output.Messages;
import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.process.Process;
import fr.xephi.authme.process.ProcessService;
import fr.xephi.authme.settings.properties.RegistrationSettings;
import fr.xephi.authme.util.Utils;
import org.bukkit.entity.Player;
/**
* Async task to add an email to an account.
*/
public class AsyncAddEmail {
public class AsyncAddEmail implements Process {
private final Player player;
private final String email;
private final Messages messages;
private final ProcessService service;
private final DataSource dataSource;
private final PlayerCache playerCache;
private final NewSetting settings;
public AsyncAddEmail(Player player, AuthMe plugin, String email, DataSource dataSource,
PlayerCache playerCache, NewSetting settings) {
this.messages = plugin.getMessages();
public AsyncAddEmail(Player player, String email, DataSource dataSource, PlayerCache playerCache,
ProcessService service) {
this.player = player;
this.email = email;
this.dataSource = dataSource;
this.playerCache = playerCache;
this.settings = settings;
this.service = service;
}
public void process() {
@Override
public void run() {
String playerName = player.getName().toLowerCase();
if (playerCache.isAuthenticated(playerName)) {
@ -42,19 +40,19 @@ public class AsyncAddEmail {
final String currentEmail = auth.getEmail();
if (currentEmail != null && !"your@email.com".equals(currentEmail)) {
messages.send(player, MessageKey.USAGE_CHANGE_EMAIL);
} else if (!Utils.isEmailCorrect(email, settings)) {
messages.send(player, MessageKey.INVALID_EMAIL);
service.send(player, MessageKey.USAGE_CHANGE_EMAIL);
} else if (!Utils.isEmailCorrect(email, service.getSettings())) {
service.send(player, MessageKey.INVALID_EMAIL);
} else if (dataSource.isEmailStored(email)) {
messages.send(player, MessageKey.EMAIL_ALREADY_USED_ERROR);
service.send(player, MessageKey.EMAIL_ALREADY_USED_ERROR);
} else {
auth.setEmail(email);
if (dataSource.updateEmail(auth)) {
playerCache.updatePlayer(auth);
messages.send(player, MessageKey.EMAIL_ADDED_SUCCESS);
service.send(player, MessageKey.EMAIL_ADDED_SUCCESS);
} else {
ConsoleLogger.showError("Could not save email for player '" + player + "'");
messages.send(player, MessageKey.ERROR);
service.send(player, MessageKey.ERROR);
}
}
} else {
@ -64,11 +62,11 @@ public class AsyncAddEmail {
private void sendUnloggedMessage(DataSource dataSource) {
if (dataSource.isAuthAvailable(player.getName())) {
messages.send(player, MessageKey.LOGIN_MESSAGE);
} else if (Settings.emailRegistration) {
messages.send(player, MessageKey.REGISTER_EMAIL_MESSAGE);
service.send(player, MessageKey.LOGIN_MESSAGE);
} else if (service.getProperty(RegistrationSettings.USE_EMAIL_REGISTRATION)) {
service.send(player, MessageKey.REGISTER_EMAIL_MESSAGE);
} 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.listener.AuthMePlayerListener;
import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.output.Messages;
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.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.TimeoutTask;
import fr.xephi.authme.util.Utils;
import fr.xephi.authme.util.Utils.GroupType;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
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;
/**
*/
public class AsynchronousJoin {
public class AsynchronousJoin implements Process {
private final AuthMe plugin;
private final Player player;
private final DataSource database;
private final String name;
private final Messages m;
private final BukkitScheduler sched;
private final ProcessService service;
private final PlayerCache playerCache;
public AsynchronousJoin(Player player, AuthMe plugin, DataSource database) {
this.m = plugin.getMessages();
public AsynchronousJoin(Player player, AuthMe plugin, DataSource database, PlayerCache playerCache,
ProcessService service) {
this.player = player;
this.plugin = plugin;
this.sched = plugin.getServer().getScheduler();
this.database = database;
this.name = player.getName().toLowerCase();
this.service = service;
this.playerCache = playerCache;
}
public void process() {
@Override
public void run() {
if (Utils.isUnrestricted(player)) {
return;
}
if (Settings.checkVeryGames) {
if (service.getProperty(HooksSettings.ENABLE_VERYGAMES_IP_CHECK)) {
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);
}
final String ip = plugin.getIP(player);
if (Settings.isAllowRestrictedIp && isNameRestricted(name, ip, player.getAddress().getHostName())) {
sched.scheduleSyncDelayedTask(plugin, new Runnable() {
if (isNameRestricted(name, ip, player.getAddress().getHostName(), service.getSettings())) {
service.scheduleSyncDelayedTask(new Runnable() {
@Override
public void run() {
AuthMePlayerListener.causeByAuthMe.putIfAbsent(name, true);
player.kickPlayer(m.retrieveSingle(MessageKey.NOT_OWNER_ERROR));
player.kickPlayer(service.retrieveMessage(MessageKey.NOT_OWNER_ERROR));
if (Settings.banUnsafeIp) {
plugin.getServer().banIP(ip);
}
@ -78,38 +83,34 @@ public class AsynchronousJoin {
});
return;
}
if (Settings.getMaxJoinPerIp > 0
if (service.getProperty(RestrictionSettings.MAX_JOIN_PER_IP) > 0
&& !plugin.getPermissionsManager().hasPermission(player, PlayerStatePermission.ALLOW_MULTIPLE_ACCOUNTS)
&& !ip.equalsIgnoreCase("127.0.0.1")
&& !ip.equalsIgnoreCase("localhost")
&& plugin.hasJoinedIp(player.getName(), ip)) {
sched.scheduleSyncDelayedTask(plugin, new Runnable() {
&& !"127.0.0.1".equalsIgnoreCase(ip)
&& !"localhost".equalsIgnoreCase(ip)
&& hasJoinedIp(player.getName(), ip, service.getSettings(), service.getAuthMe())) {
service.scheduleSyncDelayedTask(new Runnable() {
@Override
public void run() {
player.kickPlayer("A player with the same IP is already in game!");
}
});
return;
}
final Location spawnLoc = plugin.getSpawnLocation(player);
final Location spawnLoc = Spawn.getInstance().getSpawnLocation(player);
final boolean isAuthAvailable = database.isAuthAvailable(name);
if (isAuthAvailable) {
if (!Settings.noTeleport) {
if (Settings.isTeleportToSpawnEnabled || (Settings.isForceSpawnLocOnJoinEnabled && Settings.getForcedWorlds.contains(player.getWorld().getName()))) {
sched.scheduleSyncDelayedTask(plugin, new Runnable() {
service.scheduleSyncDelayedTask(new Runnable() {
@Override
public void run() {
SpawnTeleportEvent tpEvent = new SpawnTeleportEvent(player, player.getLocation(), spawnLoc, PlayerCache.getInstance().isAuthenticated(name));
plugin.getServer().getPluginManager().callEvent(tpEvent);
SpawnTeleportEvent tpEvent = new SpawnTeleportEvent(player, player.getLocation(), spawnLoc, playerCache.isAuthenticated(name));
service.callEvent(tpEvent);
if (!tpEvent.isCancelled() && player.isOnline() && tpEvent.getTo() != null
&& tpEvent.getTo().getWorld() != null) {
player.teleport(tpEvent.getTo());
}
}
});
}
}
@ -123,12 +124,12 @@ public class AsynchronousJoin {
if (ev.isCancelled()) {
plugin.inventoryProtector.sendInventoryPacket(player);
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)) {
plugin.sessions.get(name).cancel();
plugin.sessions.remove(name);
@ -137,11 +138,11 @@ public class AsynchronousJoin {
database.setUnlogged(name);
PlayerCache.getInstance().removePlayer(name);
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);
return;
} else if (Settings.sessionExpireOnIpChange) {
m.send(player, MessageKey.SESSION_EXPIRED);
service.send(player, MessageKey.SESSION_EXPIRED);
}
}
} else {
@ -154,21 +155,18 @@ public class AsynchronousJoin {
if (!Settings.noTeleport && !needFirstSpawn() && Settings.isTeleportToSpawnEnabled
|| (Settings.isForceSpawnLocOnJoinEnabled && Settings.getForcedWorlds.contains(player.getWorld().getName()))) {
sched.scheduleSyncDelayedTask(plugin, new Runnable() {
service.scheduleSyncDelayedTask(new Runnable() {
@Override
public void run() {
SpawnTeleportEvent tpEvent = new SpawnTeleportEvent(player, player.getLocation(), spawnLoc, PlayerCache.getInstance().isAuthenticated(name));
plugin.getServer().getPluginManager().callEvent(tpEvent);
if (!tpEvent.isCancelled() && player.isOnline() && tpEvent.getTo() != null
&& tpEvent.getTo().getWorld() != null) {
player.teleport(tpEvent.getTo());
SpawnTeleportEvent tpEvent = new SpawnTeleportEvent(player, player.getLocation(), spawnLoc, PlayerCache.getInstance().isAuthenticated(name));
service.callEvent(tpEvent);
if (!tpEvent.isCancelled() && player.isOnline() && tpEvent.getTo() != null
&& tpEvent.getTo().getWorld() != null) {
player.teleport(tpEvent.getTo());
}
}
}
});
}
}
if (!LimboCache.getInstance().hasLimboPlayer(name)) {
@ -176,9 +174,9 @@ public class AsynchronousJoin {
}
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
public void run() {
player.setOp(false);
@ -186,40 +184,35 @@ public class AsynchronousJoin {
player.setFlySpeed(0.0f);
player.setWalkSpeed(0.0f);
}
player.setNoDamageTicks(timeOut);
if (Settings.useEssentialsMotd) {
player.setNoDamageTicks(registrationTimeout);
if (service.getProperty(HooksSettings.USE_ESSENTIALS_MOTD)) {
player.performCommand("motd");
}
if (Settings.applyBlindEffect) {
int blindTimeOut;
if (service.getProperty(RegistrationSettings.APPLY_BLIND_EFFECT)) {
// Allow infinite blindness effect
if (timeOut <= 0) {
blindTimeOut = 99999;
} else {
blindTimeOut = timeOut;
}
int blindTimeOut = (registrationTimeout <= 0) ? 99999 : registrationTimeout;
player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, blindTimeOut, 2));
}
}
});
int msgInterval = Settings.getWarnMessageInterval;
if (timeOut > 0) {
BukkitTask id = sched.runTaskLaterAsynchronously(plugin, new TimeoutTask(plugin, name, player), timeOut);
int msgInterval = service.getProperty(RegistrationSettings.MESSAGE_INTERVAL);
if (registrationTimeout > 0) {
BukkitTask id = service.runTaskLater(new TimeoutTask(plugin, name, player), registrationTimeout);
LimboCache.getInstance().getLimboPlayer(name).setTimeoutTaskId(id);
}
String[] msg;
MessageKey msg;
if (isAuthAvailable) {
msg = m.retrieve(MessageKey.LOGIN_MESSAGE);
msg = MessageKey.LOGIN_MESSAGE;
} else {
msg = Settings.emailRegistration
? m.retrieve(MessageKey.REGISTER_EMAIL_MESSAGE)
: m.retrieve(MessageKey.REGISTER_MESSAGE);
? MessageKey.REGISTER_EMAIL_MESSAGE
: MessageKey.REGISTER_MESSAGE;
}
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);
}
}
@ -235,13 +228,11 @@ public class AsynchronousJoin {
if (!tpEvent.isCancelled()) {
if (player.isOnline() && tpEvent.getTo() != null && tpEvent.getTo().getWorld() != null) {
final Location fLoc = tpEvent.getTo();
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
service.scheduleSyncDelayedTask(new Runnable() {
@Override
public void run() {
player.teleport(fLoc);
}
});
}
}
@ -249,25 +240,23 @@ public class AsynchronousJoin {
}
private void placePlayerSafely(final Player player, final Location spawnLoc) {
if (spawnLoc == null)
return;
if (!Settings.noTeleport)
if (spawnLoc == null || service.getProperty(RestrictionSettings.NO_TELEPORT))
return;
if (Settings.isTeleportToSpawnEnabled || (Settings.isForceSpawnLocOnJoinEnabled && Settings.getForcedWorlds.contains(player.getWorld().getName())))
return;
if (!player.hasPlayedBefore())
return;
sched.scheduleSyncDelayedTask(plugin, new Runnable() {
service.scheduleSyncDelayedTask(new Runnable() {
@Override
public void run() {
if (spawnLoc.getWorld() == null) {
return;
}
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
|| top == Material.PORTAL || top == Material.ENDER_PORTAL) {
m.send(player, MessageKey.UNSAFE_QUIT_LOCATION);
service.send(player, MessageKey.UNSAFE_QUIT_LOCATION);
player.teleport(spawnLoc);
}
}
@ -281,12 +270,17 @@ public class AsynchronousJoin {
* @param name The name to check
* @param ip The IP address of the player
* @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),
* 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;
for (String entry : Settings.getRestrictedIp) {
for (String entry : settings.getProperty(RestrictionSettings.ALLOWED_RESTRICTED_USERS)) {
String[] args = entry.split(";");
String testName = args[0];
String testIp = args[1];
@ -301,4 +295,12 @@ public class AsynchronousJoin {
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 {
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)));
LimboCache.getInstance().getLimboPlayer(name).setMessageTaskId(msgT);
}
@ -175,7 +175,7 @@ public class AsynchronousLogin {
displayOtherAccounts(auth);
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) {
@ -185,7 +185,6 @@ public class AsynchronousLogin {
// makes player isLoggedin via API
PlayerCache.getInstance().addPlayer(auth);
database.setLogged(name);
plugin.otherAccounts.addPlayer(player.getUniqueId());
// As the scheduling executes the Task most likely after the current
// task, we schedule it in the end
@ -232,8 +231,8 @@ public class AsynchronousLogin {
String message = "[AuthMe] " + StringUtils.join(", ", auths) + ".";
for (Player player : Utils.getOnlinePlayers()) {
if (plugin.getPermissionsManager().hasPermission(player, AdminPermission.SEE_OTHER_ACCOUNTS)
|| (player.getName().equals(this.player.getName())
&& plugin.getPermissionsManager().hasPermission(player, PlayerPermission.SEE_OWN_ACCOUNTS))) {
|| (player.getName().equals(this.player.getName())
&& plugin.getPermissionsManager().hasPermission(player, PlayerPermission.SEE_OWN_ACCOUNTS))) {
player.sendMessage("[AuthMe] The player " + auth.getNickname() + " has " + auths.size() + " accounts");
player.sendMessage(message);
}

View File

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

View File

@ -74,21 +74,24 @@ public class ProcessSyncronousPlayerLogout implements Runnable {
int interval = Settings.getWarnMessageInterval;
BukkitScheduler sched = player.getServer().getScheduler();
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);
}
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);
if (player.isInsideVehicle() && player.getVehicle() != null)
if (player.isInsideVehicle() && player.getVehicle() != null) {
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);
restoreSpeedEffect();
// Player is now logout... Time to fire event !
Bukkit.getServer().getPluginManager().callEvent(new LogoutEvent(player));
if (Settings.bungee)
if (Settings.bungee) {
sendBungeeMessage();
}
m.send(player, MessageKey.LOGOUT_SUCCESS);
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.limbo.LimboCache;
import fr.xephi.authme.cache.limbo.LimboPlayer;
import fr.xephi.authme.datasource.CacheDataSource;
import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.util.StringUtils;
import fr.xephi.authme.util.Utils;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitTask;
/**
*/
public class AsynchronousQuit {
protected final AuthMe plugin;
protected final DataSource database;
protected final Player player;
private final AuthMe plugin;
private final DataSource database;
private final Player player;
private final String name;
private boolean isOp = false;
private boolean needToChange = 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,
boolean isKick) {
this.player = p;
@ -43,9 +35,7 @@ public class AsynchronousQuit {
}
public void process() {
if (player == null)
return;
if (Utils.isUnrestricted(player)) {
if (player == null || Utils.isUnrestricted(player)) {
return;
}
@ -54,7 +44,9 @@ public class AsynchronousQuit {
if (PlayerCache.getInstance().isAuthenticated(name)) {
if (Settings.isSaveQuitLocationEnabled) {
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);
}
PlayerAuth auth = new PlayerAuth(name, ip, System.currentTimeMillis(), player.getName());
@ -63,14 +55,11 @@ public class AsynchronousQuit {
LimboPlayer limbo = LimboCache.getInstance().getLimboPlayer(name);
if (limbo != null) {
if (limbo.getGroup() != null && !limbo.getGroup().isEmpty())
if (!StringUtils.isEmpty(limbo.getGroup())) {
Utils.addNormal(player, limbo.getGroup());
}
needToChange = true;
isOp = limbo.getOperator();
if (limbo.getTimeoutTaskId() != null)
limbo.getTimeoutTaskId().cancel();
if (limbo.getMessageTaskId() != null)
limbo.getMessageTaskId().cancel();
LimboCache.getInstance().deleteLimboPlayer(name);
}
if (Settings.isSessionsEnabled && !isKick) {
@ -100,12 +89,15 @@ public class AsynchronousQuit {
if (plugin.isEnabled()) {
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() {
PlayerCache.getInstance().removePlayer(name);
if (database.isLogged(name))
database.setUnlogged(name);
database.setUnlogged(name);
plugin.sessions.remove(name);
}
}

View File

@ -1,5 +1,10 @@
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.cache.auth.PlayerAuth;
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.Settings;
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)) {
m.send(player, MessageKey.NAME_ALREADY_REGISTERED);
return false;
} else if (Settings.getmaxRegPerIp > 0
&& !plugin.getPermissionsManager().hasPermission(player, PlayerStatePermission.ALLOW_MULTIPLE_ACCOUNTS)
} else if(Settings.getmaxRegPerIp > 0
&& !ip.equalsIgnoreCase("127.0.0.1")
&& !ip.equalsIgnoreCase("localhost")
&& database.getAllAuthsByIp(ip).size() >= Settings.getmaxRegPerIp) {
m.send(player, MessageKey.MAX_REGISTER_EXCEEDED);
return false;
&& !plugin.getPermissionsManager().hasPermission(player, PlayerStatePermission.ALLOW_MULTIPLE_ACCOUNTS)) {
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 false;
}
}
return true;
}
@ -96,11 +102,16 @@ public class AsyncRegister {
}
private void emailRegister() {
if (Settings.getmaxRegPerEmail > 0
&& !plugin.getPermissionsManager().hasPermission(player, PlayerStatePermission.ALLOW_MULTIPLE_ACCOUNTS)
&& database.countAuthsByEmail(email) >= Settings.getmaxRegPerEmail) {
m.send(player, MessageKey.MAX_REGISTER_EXCEEDED);
return;
if(Settings.getmaxRegPerEmail > 0
&& !ip.equalsIgnoreCase("127.0.0.1")
&& !ip.equalsIgnoreCase("localhost")
&& !plugin.getPermissionsManager().hasPermission(player, PlayerStatePermission.ALLOW_MULTIPLE_ACCOUNTS)) {
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);
PlayerAuth auth = PlayerAuth.builder()
@ -146,7 +157,6 @@ public class AsyncRegister {
plugin.getManagement().performLogin(player, "dontneed", true);
}
plugin.otherAccounts.addPlayer(player.getUniqueId());
ProcessSyncPasswordRegister sync = new ProcessSyncPasswordRegister(player, plugin, settings);
plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, sync);

View File

@ -52,14 +52,13 @@ public class ProcessSyncEmailRegister implements Runnable {
int msgInterval = Settings.getWarnMessageInterval;
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) {
limbo.getMessageTaskId().cancel();
BukkitTask nwMsg = sched.runTaskAsynchronously(plugin, new MessageTask(plugin, name, m.retrieve(MessageKey.LOGIN_MESSAGE), msgInterval));
if (time != 0) {
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);
}

View File

@ -1,16 +1,7 @@
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.ByteStreams;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ConsoleLogger;
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.output.MessageKey;
import fr.xephi.authme.output.Messages;
import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.properties.HooksSettings;
import fr.xephi.authme.task.MessageTask;
import fr.xephi.authme.task.TimeoutTask;
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.
*
* @param player Player
* @param plugin AuthMe
* @param player Player
* @param plugin AuthMe
* @param settings The plugin settings
*/
public ProcessSyncPasswordRegister(Player player, AuthMe plugin, NewSetting settings) {
@ -77,11 +75,10 @@ public class ProcessSyncPasswordRegister implements Runnable {
BukkitScheduler sched = plugin.getServer().getScheduler();
BukkitTask task;
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);
}
task = sched.runTaskAsynchronously(plugin, new MessageTask(plugin, name,
m.retrieve(MessageKey.LOGIN_MESSAGE), interval));
task = sched.runTask(plugin, new MessageTask(plugin, name, MessageKey.LOGIN_MESSAGE, interval));
cache.getLimboPlayer(name).setMessageTaskId(task);
if (player.isInsideVehicle() && player.getVehicle() != null) {
player.getVehicle().eject();
@ -158,7 +155,7 @@ public class ProcessSyncPasswordRegister implements Runnable {
// Register is now finished; we can force all commands
forceCommands();
sendTo();
}

View File

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

View File

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

View File

@ -2,7 +2,6 @@ package fr.xephi.authme.settings;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.util.StringUtils;
import org.bukkit.Bukkit;
@ -73,34 +72,32 @@ public class Spawn extends CustomConfiguration {
}
public Location getSpawn() {
try {
if (containsAll("spawn.world", "spawn.x", "spawn.y", "spawn.z", "spawn.yaw", "spawn.pitch")) {
String worldName = getString("spawn.world");
World world = Bukkit.getWorld(worldName);
if (StringUtils.isEmpty(worldName) || world == null) {
return null;
if (!StringUtils.isEmpty(worldName) && world != 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() {
try {
String worldName;
World world;
if (StringUtils.isEmpty(worldName = getString("firstspawn.world")) ||
(world = Bukkit.getWorld(worldName)) == null) {
return null;
if (containsAll("firstspawn.world", "firstspawn.x", "firstspawn.y",
"firstspawn.z", "firstspawn.yaw", "firstspawn.pitch")) {
String worldName = getString("firstspawn.world");
World world = Bukkit.getWorld(worldName);
if (!StringUtils.isEmpty(worldName) && world != 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

View File

@ -39,7 +39,7 @@ public class RegistrationSettings implements SettingsClass {
newProperty("settings.registration.doubleEmailCheck", false);
@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"})
public static final Property<Boolean> FORCE_KICK_AFTER_REGISTER =
newProperty("settings.registration.forceKickAfterRegister", false);

View File

@ -64,7 +64,7 @@ public class RestrictionSettings implements SettingsClass {
@Comment({
"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 =
newProperty("settings.restrictions.AllowRestrictedUser", false);

View File

@ -53,12 +53,12 @@ public class ChangePasswordTask implements Runnable {
@Override
public void run() {
ByteArrayDataOutput out = ByteStreams.newDataOutput();
out.writeUTF("Forward");
out.writeUTF("ALL");
out.writeUTF("AuthMe");
out.writeUTF("changepassword;" + name + ";" + hash + ";" + salt);
player.sendPluginMessage(plugin, "BungeeCord", out.toByteArray());
ByteArrayDataOutput out = ByteStreams.newDataOutput();
out.writeUTF("Forward");
out.writeUTF("ALL");
out.writeUTF("AuthMe");
out.writeUTF("changepassword;" + name + ";" + hash + ";" + salt);
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.cache.auth.PlayerCache;
import fr.xephi.authme.cache.limbo.LimboCache;
import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.util.Utils;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitTask;
@ -24,32 +25,31 @@ public class MessageTask implements Runnable {
* @param strings String[]
* @param interval int
*/
public MessageTask(AuthMe plugin, String name, String[] strings,
int interval) {
public MessageTask(AuthMe plugin, String name, String[] strings, int interval) {
this.plugin = plugin;
this.name = name;
this.msg = strings;
this.interval = interval;
}
/**
* Method run.
*
* @see java.lang.Runnable#run()
*/
public MessageTask(AuthMe plugin, String name, MessageKey messageKey, int interval) {
this(plugin, name, plugin.getMessages().retrieve(messageKey), interval);
}
@Override
public void run() {
if (PlayerCache.getInstance().isAuthenticated(name))
if (PlayerCache.getInstance().isAuthenticated(name)) {
return;
}
for (Player player : Utils.getOnlinePlayers()) {
if (player.getName().toLowerCase().equals(name)) {
if (player.getName().equalsIgnoreCase(name)) {
for (String ms : msg) {
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)) {
LimboCache.getInstance().getLimboPlayer(name).setMessageTaskId(late);
LimboCache.getInstance().getLimboPlayer(name).setMessageTaskId(nextTask);
}
return;
}

View File

@ -4,14 +4,10 @@ import fr.xephi.authme.AuthMe;
import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.output.Messages;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
/**
*/
public class TimeoutTask implements Runnable {
private final AuthMe plugin;
private final String name;
private final Messages m;
private final Player player;
@ -25,38 +21,14 @@ public class TimeoutTask implements Runnable {
*/
public TimeoutTask(AuthMe plugin, String name, Player player) {
this.m = plugin.getMessages();
this.plugin = plugin;
this.name = name;
this.player = player;
}
/**
* Method getName.
*
* @return String
*/
public String getName() {
return name;
}
/**
* Method run.
*
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
if (PlayerCache.getInstance().isAuthenticated(name)) {
return;
if (!PlayerCache.getInstance().isAuthenticated(name)) {
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.datasource.DataSource;
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.crypts.HashedPassword;
import fr.xephi.authme.security.crypts.SHA256;
@ -58,12 +60,17 @@ public final class MigrationService {
if (DataSourceType.FILE == settings.getProperty(DatabaseSettings.BACKEND)) {
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!");
ForceFlatToSqlite converter = new ForceFlatToSqlite(dataSource, settings);
DataSource result = converter.run();
if (result == null) {
throw new IllegalStateException("Error during conversion from flatfile to SQLite");
} else {
return result;
FlatFile flatFile = (FlatFile) dataSource;
try {
SQLite sqlite = new SQLite(settings);
ForceFlatToSqlite converter = new ForceFlatToSqlite(flatFile, sqlite);
converter.run();
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;

View File

@ -2,15 +2,13 @@ package fr.xephi.authme.util;
import java.text.DecimalFormat;
/**
*/
@SuppressWarnings("UnusedDeclaration")
public class Profiler {
/**
* Defines the past time in milliseconds.
*/
private long time = 0;
/**
* 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) {
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) {
@ -216,8 +215,7 @@ public final class Utils {
ConsoleLogger.showError("Unknown list of online players of type " + type);
}
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
ConsoleLogger.showError("Could not retrieve list of online players: ["
+ e.getClass().getName() + "] " + e.getMessage());
ConsoleLogger.logException("Could not retrieve list of online players:", e);
}
return Collections.emptyList();
}

View File

@ -1,5 +1,5 @@
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!'
reg_voluntarily: 'Du kannst dich mit folgendem Befehl registrieren "/register <passwort> <passwortBestätigen>"'
usage_log: '&cBenutze: /login <passwort>'
@ -9,11 +9,11 @@ reg_disabled: '&cRegistrierungen sind deaktiviert'
valid_session: '&2Erfolgreich eingeloggt!'
login: '&2Erfolgreich eingeloggt!'
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>'
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!'
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>"'
reg_msg: '&3Bitte registriere Dich mit "/register <passwort> <passwortBestä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!'
user_unknown: '&cBenutzername nicht registriert!'
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!'
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!'
logout: '&2Erfolgreich ausgeloggt'
same_nick: '&4Jemand mit diesem Namen spielt bereits auf dem Server!'
registered: '&2Erfolgreich registriert!'
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'
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'
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'
usage_captcha: '&3Um dich einzuloggen, tippe dieses Captcha so ein: /captcha <theCaptcha>'
wrong_captcha: '&cFalsches Captcha, bitte nutze: /captcha THE_CAPTCHA'
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!'
usage_email_add: '&cBenutze: /email add <email> <bestätigeEmail>'
usage_email_change: '&cBenutze: /email change <alteEmail> <neueEmail>'
usage_email_recovery: '&cBenutze: /email recovery <Email>'
new_email_invalid: '&cDie neue Email ist ungültig!'
old_email_invalid: '&cDie alte Email ist ungültig!'
email_invalid: '&cUngültige Email'
email_added: '&2Email hinzugefügt!'
email_confirm: '&cBitte bestätige deine Email!'
email_changed: '&2Email aktualisiert!'
email_send: '&2Wiederherstellungs-Email wurde gesendet!'
email_exists: '&cEine Wiederherstellungs-Email wurde bereits versandt! Nutze folgenden Befehl um eine neue Email zu versenden:'
country_banned: '&4Dein Land ist gesperrt'
new_email_invalid: '&cDie neue E-Mail ist ungültig!'
old_email_invalid: '&cDie alte E-Mail ist ungültig!'
email_invalid: '&cUngültige E-Mail!'
email_added: '&2E-Mail hinzugefügt!'
email_confirm: '&cBitte bestätige Deine E-Mail!'
email_changed: '&2E-Mail aktualisiert!'
email_send: '&2Wiederherstellungs-E-Mail wurde gesendet!'
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!'
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'
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'
# TODO email_already_used: '&4The email address is already being used'
# TODO invalid_name_case: 'You should join using username %valid, not %invalid.'
# TODO not_owner_error: 'You are not the owner of this account. Please try another name!'
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.'
two_factor_create: '&2Dein geheimer Code ist %code. Du kannst ihn hier abfragen: %url'
email_already_used: '&4Diese E-Mail-Adresse wird bereits genutzt.'
invalid_name_case: 'Dein registrierter Benutzername ist &2%valid&f - nicht &4%invalid&f.'
not_owner_error: 'Du bist nicht der Besitzer dieses Accounts. Bitte wähle einen anderen Namen!'

View File

@ -12,7 +12,7 @@ login: '&2Successful login!'
vb_nonActiv: '&cYour account isn''t activated yet, please check your emails!'
user_regged: '&cYou already have registered this username!'
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!'
error: '&4An unexpected error occurred, please contact an administrator!'
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!'
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'
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.'

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.security.crypts.HashedPassword;

View File

@ -1,14 +1,13 @@
package fr.xephi.authme.command;
import static fr.xephi.authme.permission.DefaultPermission.OP_ONLY;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import fr.xephi.authme.permission.AdminPermission;
import fr.xephi.authme.permission.PermissionNode;
import fr.xephi.authme.util.StringUtils;
import fr.xephi.authme.util.WrapperMock;
import org.junit.BeforeClass;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
@ -17,13 +16,12 @@ import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import org.junit.BeforeClass;
import org.junit.Test;
import fr.xephi.authme.permission.AdminPermission;
import fr.xephi.authme.permission.PermissionNode;
import fr.xephi.authme.util.StringUtils;
import fr.xephi.authme.util.WrapperMock;
import static fr.xephi.authme.permission.DefaultPermission.OP_ONLY;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
/**
* Test for {@link CommandInitializer} to guarantee the integrity of the defined commands.
@ -241,15 +239,11 @@ public class CommandInitializerTest {
public void shouldNotHavePlayerPermissionIfDefaultsToOpOnly() {
// given
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
public void accept(CommandDescription command, int depth) {
CommandPermissions permissions = command.getCommandPermissions();
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 "
+ "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 org.junit.Test;
import java.util.Arrays;
import java.util.List;
import static fr.xephi.authme.datasource.AuthMeMatchers.equalToHash;
import static fr.xephi.authme.datasource.AuthMeMatchers.hasAuthBasicData;
import static fr.xephi.authme.datasource.AuthMeMatchers.hasAuthLocation;
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.Matchers.equalTo;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertThat;
import static org.junit.Assume.assumeThat;
/**
* Abstract class for data source integration tests.
@ -126,15 +129,9 @@ public abstract class AbstractDataSourceIntegrationTest {
// then
assertThat(response, equalTo(true));
assertThat(authList, hasSize(2));
assertThat(authList, hasItem(hasAuthBasicData("bobby", "Bobby", "your@email.com", "123.45.67.89")));
assertThat(newAuthList, hasSize(3));
boolean hasBobby = false;
for (PlayerAuth auth : authList) {
if (auth.getNickname().equals("bobby")) {
hasBobby = true;
break;
}
}
assertThat(hasBobby, equalTo(true));
assertThat(newAuthList, hasItem(hasAuthBasicData("bobby", "Bobby", "your@email.com", "123.45.67.89")));
}
@Test
@ -201,4 +198,106 @@ public abstract class AbstractDataSourceIntegrationTest {
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;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ConsoleLoggerTestInitializer;
import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.datasource.DataSource;
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.Settings;
import fr.xephi.authme.settings.properties.RegistrationSettings;
import fr.xephi.authme.util.WrapperMock;
import org.bukkit.entity.Player;
import org.junit.After;
@ -27,11 +26,10 @@ import static org.mockito.Mockito.when;
*/
public class AsyncAddEmailTest {
private Messages messages;
private Player player;
private DataSource dataSource;
private PlayerCache playerCache;
private NewSetting settings;
private ProcessService service;
@BeforeClass
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
@After
public void removeFieldValues() {
messages = null;
player = null;
dataSource = null;
playerCache = null;
service = null;
}
@Test
@ -61,11 +59,11 @@ public class AsyncAddEmailTest {
given(dataSource.updateEmail(any(PlayerAuth.class))).willReturn(true);
// when
process.process();
process.run();
// then
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(playerCache).updatePlayer(auth);
}
@ -83,11 +81,11 @@ public class AsyncAddEmailTest {
given(dataSource.updateEmail(any(PlayerAuth.class))).willReturn(false);
// when
process.process();
process.run();
// then
verify(dataSource).updateEmail(auth);
verify(messages).send(player, MessageKey.ERROR);
verify(service).send(player, MessageKey.ERROR);
}
@Test
@ -102,10 +100,10 @@ public class AsyncAddEmailTest {
given(dataSource.isEmailStored("some.mail@example.org")).willReturn(false);
// when
process.process();
process.run();
// then
verify(messages).send(player, MessageKey.USAGE_CHANGE_EMAIL);
verify(service).send(player, MessageKey.USAGE_CHANGE_EMAIL);
verify(playerCache, never()).updatePlayer(any(PlayerAuth.class));
}
@ -121,10 +119,10 @@ public class AsyncAddEmailTest {
given(dataSource.isEmailStored("invalid_mail")).willReturn(false);
// when
process.process();
process.run();
// then
verify(messages).send(player, MessageKey.INVALID_EMAIL);
verify(service).send(player, MessageKey.INVALID_EMAIL);
verify(playerCache, never()).updatePlayer(any(PlayerAuth.class));
}
@ -140,10 +138,10 @@ public class AsyncAddEmailTest {
given(dataSource.isEmailStored("player@mail.tld")).willReturn(true);
// when
process.process();
process.run();
// 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));
}
@ -156,10 +154,10 @@ public class AsyncAddEmailTest {
given(dataSource.isAuthAvailable("Username12")).willReturn(true);
// when
process.process();
process.run();
// then
verify(messages).send(player, MessageKey.LOGIN_MESSAGE);
verify(service).send(player, MessageKey.LOGIN_MESSAGE);
verify(playerCache, never()).updatePlayer(any(PlayerAuth.class));
}
@ -170,13 +168,13 @@ public class AsyncAddEmailTest {
given(player.getName()).willReturn("user");
given(playerCache.isAuthenticated("user")).willReturn(false);
given(dataSource.isAuthAvailable("user")).willReturn(false);
Settings.emailRegistration = true;
given(service.getProperty(RegistrationSettings.USE_EMAIL_REGISTRATION)).willReturn(true);
// when
process.process();
process.run();
// then
verify(messages).send(player, MessageKey.REGISTER_EMAIL_MESSAGE);
verify(service).send(player, MessageKey.REGISTER_EMAIL_MESSAGE);
verify(playerCache, never()).updatePlayer(any(PlayerAuth.class));
}
@ -187,13 +185,13 @@ public class AsyncAddEmailTest {
given(player.getName()).willReturn("user");
given(playerCache.isAuthenticated("user")).willReturn(false);
given(dataSource.isAuthAvailable("user")).willReturn(false);
Settings.emailRegistration = false;
given(service.getProperty(RegistrationSettings.USE_EMAIL_REGISTRATION)).willReturn(false);
// when
process.process();
process.run();
// then
verify(messages).send(player, MessageKey.REGISTER_MESSAGE);
verify(service).send(player, MessageKey.REGISTER_MESSAGE);
verify(playerCache, never()).updatePlayer(any(PlayerAuth.class));
}
@ -204,14 +202,12 @@ public class AsyncAddEmailTest {
* @return The created process
*/
private AsyncAddEmail createProcess(String email) {
messages = mock(Messages.class);
AuthMe authMe = mock(AuthMe.class);
when(authMe.getMessages()).thenReturn(messages);
player = mock(Player.class);
dataSource = mock(DataSource.class);
playerCache = mock(PlayerCache.class);
settings = mock(NewSetting.class);
return new AsyncAddEmail(player, authMe, email, dataSource, playerCache, settings);
service = mock(ProcessService.class);
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