diff --git a/pom.xml b/pom.xml
index 3c19ea9a3..0cd2db1d5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -27,7 +27,7 @@
jenkins
- http://ci.codemc.org/job/AuthMeReloaded/
+ http://ci.codemc.org/job/AuthMe/job/AuthMeReloaded/
@@ -258,6 +258,10 @@
ch.jalu.configme
fr.xephi.authme.libs.ch.jalu.configme
+
+ ch.jalu.datasourcecolumns
+ fr.xephi.authme.libs.ch.jalu.datasourcecolumns
+
com.zaxxer.hikari
fr.xephi.authme.libs.com.zaxxer.hikari
@@ -399,7 +403,7 @@
com.google.guava
guava
- 24.0-jre
+ 24.1-jre
true
@@ -799,6 +803,13 @@
+
+ ch.jalu
+ datasourcecolumns
+ 0.1-SNAPSHOT
+ true
+
+
@@ -819,7 +830,7 @@
org.mockito
mockito-core
test
- 2.15.0
+ 2.16.0
hamcrest-core
diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/GetEmailCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/GetEmailCommand.java
index a7f327a10..b66914387 100644
--- a/src/main/java/fr/xephi/authme/command/executable/authme/GetEmailCommand.java
+++ b/src/main/java/fr/xephi/authme/command/executable/authme/GetEmailCommand.java
@@ -1,8 +1,8 @@
package fr.xephi.authme.command.executable.authme;
+import ch.jalu.datasourcecolumns.data.DataSourceValue;
import fr.xephi.authme.command.ExecutableCommand;
import fr.xephi.authme.datasource.DataSource;
-import fr.xephi.authme.datasource.DataSourceResult;
import fr.xephi.authme.message.MessageKey;
import fr.xephi.authme.service.CommonService;
import org.bukkit.command.CommandSender;
@@ -25,8 +25,8 @@ public class GetEmailCommand implements ExecutableCommand {
public void executeCommand(CommandSender sender, List arguments) {
String playerName = arguments.isEmpty() ? sender.getName() : arguments.get(0);
- DataSourceResult email = dataSource.getEmail(playerName);
- if (email.playerExists()) {
+ DataSourceValue email = dataSource.getEmail(playerName);
+ if (email.rowExists()) {
sender.sendMessage("[AuthMe] " + playerName + "'s email: " + email.getValue());
} else {
commonService.send(sender, MessageKey.UNKNOWN_USER);
diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/debug/TestEmailSender.java b/src/main/java/fr/xephi/authme/command/executable/authme/debug/TestEmailSender.java
index f3580d326..02bd4a213 100644
--- a/src/main/java/fr/xephi/authme/command/executable/authme/debug/TestEmailSender.java
+++ b/src/main/java/fr/xephi/authme/command/executable/authme/debug/TestEmailSender.java
@@ -1,8 +1,8 @@
package fr.xephi.authme.command.executable.authme.debug;
+import ch.jalu.datasourcecolumns.data.DataSourceValue;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.datasource.DataSource;
-import fr.xephi.authme.datasource.DataSourceResult;
import fr.xephi.authme.mail.SendMailSsl;
import fr.xephi.authme.permission.DebugSectionPermissions;
import fr.xephi.authme.permission.PermissionNode;
@@ -82,8 +82,8 @@ class TestEmailSender implements DebugSection {
*/
private String getEmail(CommandSender sender, List arguments) {
if (arguments.isEmpty()) {
- DataSourceResult emailResult = dataSource.getEmail(sender.getName());
- if (!emailResult.playerExists()) {
+ DataSourceValue emailResult = dataSource.getEmail(sender.getName());
+ if (!emailResult.rowExists()) {
sender.sendMessage(ChatColor.RED + "Please provide an email address, "
+ "e.g. /authme debug mail test@example.com");
return null;
diff --git a/src/main/java/fr/xephi/authme/command/executable/email/RecoverEmailCommand.java b/src/main/java/fr/xephi/authme/command/executable/email/RecoverEmailCommand.java
index 339980a34..0a3a96945 100644
--- a/src/main/java/fr/xephi/authme/command/executable/email/RecoverEmailCommand.java
+++ b/src/main/java/fr/xephi/authme/command/executable/email/RecoverEmailCommand.java
@@ -1,10 +1,10 @@
package fr.xephi.authme.command.executable.email;
+import ch.jalu.datasourcecolumns.data.DataSourceValue;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.command.PlayerCommand;
import fr.xephi.authme.data.auth.PlayerCache;
import fr.xephi.authme.datasource.DataSource;
-import fr.xephi.authme.datasource.DataSourceResult;
import fr.xephi.authme.mail.EmailService;
import fr.xephi.authme.message.MessageKey;
import fr.xephi.authme.service.BukkitService;
@@ -58,8 +58,8 @@ public class RecoverEmailCommand extends PlayerCommand {
return;
}
- DataSourceResult emailResult = dataSource.getEmail(playerName);
- if (!emailResult.playerExists()) {
+ DataSourceValue emailResult = dataSource.getEmail(playerName);
+ if (!emailResult.rowExists()) {
commonService.send(player, MessageKey.USAGE_REGISTER);
return;
}
diff --git a/src/main/java/fr/xephi/authme/data/VerificationCodeManager.java b/src/main/java/fr/xephi/authme/data/VerificationCodeManager.java
index a6ba75c6e..c5c2d7257 100644
--- a/src/main/java/fr/xephi/authme/data/VerificationCodeManager.java
+++ b/src/main/java/fr/xephi/authme/data/VerificationCodeManager.java
@@ -1,7 +1,7 @@
package fr.xephi.authme.data;
+import ch.jalu.datasourcecolumns.data.DataSourceValue;
import fr.xephi.authme.datasource.DataSource;
-import fr.xephi.authme.datasource.DataSourceResult;
import fr.xephi.authme.initialization.HasCleanup;
import fr.xephi.authme.initialization.SettingsDependent;
import fr.xephi.authme.mail.EmailService;
@@ -103,8 +103,8 @@ public class VerificationCodeManager implements SettingsDependent, HasCleanup {
*/
public boolean hasEmail(String name) {
boolean result = false;
- DataSourceResult emailResult = dataSource.getEmail(name);
- if (emailResult.playerExists()) {
+ DataSourceValue emailResult = dataSource.getEmail(name);
+ if (emailResult.rowExists()) {
final String email = emailResult.getValue();
if (!Utils.isEmailEmpty(email)) {
result = true;
@@ -130,8 +130,8 @@ public class VerificationCodeManager implements SettingsDependent, HasCleanup {
* @param name the name of the player to generate a code for
*/
private void generateCode(String name) {
- DataSourceResult emailResult = dataSource.getEmail(name);
- if (emailResult.playerExists()) {
+ DataSourceValue emailResult = dataSource.getEmail(name);
+ if (emailResult.rowExists()) {
final String email = emailResult.getValue();
if (!Utils.isEmailEmpty(email)) {
String code = RandomStringUtils.generateNum(6); // 6 digits code
diff --git a/src/main/java/fr/xephi/authme/datasource/AbstractSqlDataSource.java b/src/main/java/fr/xephi/authme/datasource/AbstractSqlDataSource.java
new file mode 100644
index 000000000..0c40c479d
--- /dev/null
+++ b/src/main/java/fr/xephi/authme/datasource/AbstractSqlDataSource.java
@@ -0,0 +1,169 @@
+package fr.xephi.authme.datasource;
+
+import ch.jalu.datasourcecolumns.data.DataSourceValue;
+import ch.jalu.datasourcecolumns.data.DataSourceValueImpl;
+import ch.jalu.datasourcecolumns.data.DataSourceValues;
+import ch.jalu.datasourcecolumns.predicate.AlwaysTruePredicate;
+import fr.xephi.authme.data.auth.PlayerAuth;
+import fr.xephi.authme.datasource.columnshandler.AuthMeColumns;
+import fr.xephi.authme.datasource.columnshandler.AuthMeColumnsHandler;
+import fr.xephi.authme.security.crypts.HashedPassword;
+
+import java.sql.SQLException;
+import java.util.Collections;
+import java.util.List;
+
+import static ch.jalu.datasourcecolumns.data.UpdateValues.with;
+import static ch.jalu.datasourcecolumns.predicate.StandardPredicates.eq;
+import static ch.jalu.datasourcecolumns.predicate.StandardPredicates.eqIgnoreCase;
+import static fr.xephi.authme.datasource.SqlDataSourceUtils.logSqlException;
+
+/**
+ * Common type for SQL-based data sources. Classes implementing this
+ * must ensure that {@link #columnsHandler} is initialized on creation.
+ */
+public abstract class AbstractSqlDataSource implements DataSource {
+
+ protected AuthMeColumnsHandler columnsHandler;
+
+ @Override
+ public boolean isAuthAvailable(String user) {
+ try {
+ return columnsHandler.retrieve(user, AuthMeColumns.NAME).rowExists();
+ } catch (SQLException e) {
+ logSqlException(e);
+ return false;
+ }
+ }
+
+ @Override
+ public HashedPassword getPassword(String user) {
+ try {
+ DataSourceValues values = columnsHandler.retrieve(user, AuthMeColumns.PASSWORD, AuthMeColumns.SALT);
+ if (values.rowExists()) {
+ return new HashedPassword(values.get(AuthMeColumns.PASSWORD), values.get(AuthMeColumns.SALT));
+ }
+ } catch (SQLException e) {
+ logSqlException(e);
+ }
+ return null;
+ }
+
+ @Override
+ public boolean saveAuth(PlayerAuth auth) {
+ return columnsHandler.insert(auth,
+ AuthMeColumns.NAME, AuthMeColumns.NICK_NAME, AuthMeColumns.PASSWORD, AuthMeColumns.SALT,
+ AuthMeColumns.EMAIL, AuthMeColumns.REGISTRATION_DATE, AuthMeColumns.REGISTRATION_IP);
+ }
+
+ @Override
+ public boolean hasSession(String user) {
+ try {
+ DataSourceValue result = columnsHandler.retrieve(user, AuthMeColumns.HAS_SESSION);
+ return result.rowExists() && Integer.valueOf(1).equals(result.getValue());
+ } catch (SQLException e) {
+ logSqlException(e);
+ return false;
+ }
+ }
+
+ @Override
+ public boolean updateSession(PlayerAuth auth) {
+ return columnsHandler.update(auth, AuthMeColumns.LAST_IP, AuthMeColumns.LAST_LOGIN, AuthMeColumns.NICK_NAME);
+ }
+
+ @Override
+ public boolean updatePassword(PlayerAuth auth) {
+ return updatePassword(auth.getNickname(), auth.getPassword());
+ }
+
+ @Override
+ public boolean updatePassword(String user, HashedPassword password) {
+ return columnsHandler.update(user,
+ with(AuthMeColumns.PASSWORD, password.getHash())
+ .and(AuthMeColumns.SALT, password.getSalt()).build());
+ }
+
+ @Override
+ public boolean updateQuitLoc(PlayerAuth auth) {
+ return columnsHandler.update(auth,
+ AuthMeColumns.LOCATION_X, AuthMeColumns.LOCATION_Y, AuthMeColumns.LOCATION_Z,
+ AuthMeColumns.LOCATION_WORLD, AuthMeColumns.LOCATION_YAW, AuthMeColumns.LOCATION_PITCH);
+ }
+
+ @Override
+ public List getAllAuthsByIp(String ip) {
+ try {
+ return columnsHandler.retrieve(eq(AuthMeColumns.LAST_IP, ip), AuthMeColumns.NAME);
+ } catch (SQLException e) {
+ logSqlException(e);
+ return Collections.emptyList();
+ }
+ }
+
+ @Override
+ public int countAuthsByEmail(String email) {
+ return columnsHandler.count(eqIgnoreCase(AuthMeColumns.EMAIL, email));
+ }
+
+ @Override
+ public boolean updateEmail(PlayerAuth auth) {
+ return columnsHandler.update(auth, AuthMeColumns.EMAIL);
+ }
+
+ @Override
+ public boolean isLogged(String user) {
+ try {
+ DataSourceValue result = columnsHandler.retrieve(user, AuthMeColumns.IS_LOGGED);
+ return result.rowExists() && Integer.valueOf(1).equals(result.getValue());
+ } catch (SQLException e) {
+ logSqlException(e);
+ return false;
+ }
+ }
+
+ @Override
+ public void setLogged(String user) {
+ columnsHandler.update(user, AuthMeColumns.IS_LOGGED, 1);
+ }
+
+ @Override
+ public void setUnlogged(String user) {
+ columnsHandler.update(user, AuthMeColumns.IS_LOGGED, 0);
+ }
+
+ @Override
+ public void grantSession(String user) {
+ columnsHandler.update(user, AuthMeColumns.HAS_SESSION, 1);
+ }
+
+ @Override
+ public void revokeSession(String user) {
+ columnsHandler.update(user, AuthMeColumns.HAS_SESSION, 0);
+ }
+
+ @Override
+ public void purgeLogged() {
+ columnsHandler.update(eq(AuthMeColumns.IS_LOGGED, 1), AuthMeColumns.IS_LOGGED, 0);
+ }
+
+ @Override
+ public int getAccountsRegistered() {
+ return columnsHandler.count(new AlwaysTruePredicate<>());
+ }
+
+ @Override
+ public boolean updateRealName(String user, String realName) {
+ return columnsHandler.update(user, AuthMeColumns.NICK_NAME, realName);
+ }
+
+ @Override
+ public DataSourceValue getEmail(String user) {
+ try {
+ return columnsHandler.retrieve(user, AuthMeColumns.EMAIL);
+ } catch (SQLException e) {
+ logSqlException(e);
+ return DataSourceValueImpl.unknownRow();
+ }
+ }
+}
diff --git a/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java b/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java
index 0926def86..165560b1e 100644
--- a/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java
+++ b/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java
@@ -1,5 +1,7 @@
package fr.xephi.authme.datasource;
+import ch.jalu.datasourcecolumns.data.DataSourceValue;
+import ch.jalu.datasourcecolumns.data.DataSourceValueImpl;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
@@ -244,10 +246,10 @@ public class CacheDataSource implements DataSource {
}
@Override
- public DataSourceResult getEmail(String user) {
+ public DataSourceValue getEmail(String user) {
return cachedAuths.getUnchecked(user)
- .map(auth -> DataSourceResult.of(auth.getEmail()))
- .orElse(DataSourceResult.unknownPlayer());
+ .map(auth -> DataSourceValueImpl.of(auth.getEmail()))
+ .orElse(DataSourceValueImpl.unknownRow());
}
@Override
diff --git a/src/main/java/fr/xephi/authme/datasource/DataSource.java b/src/main/java/fr/xephi/authme/datasource/DataSource.java
index b6e09fff9..6ce28852f 100644
--- a/src/main/java/fr/xephi/authme/datasource/DataSource.java
+++ b/src/main/java/fr/xephi/authme/datasource/DataSource.java
@@ -1,5 +1,6 @@
package fr.xephi.authme.datasource;
+import ch.jalu.datasourcecolumns.data.DataSourceValue;
import fr.xephi.authme.data.auth.PlayerAuth;
import fr.xephi.authme.initialization.Reloadable;
import fr.xephi.authme.security.crypts.HashedPassword;
@@ -216,7 +217,7 @@ public interface DataSource extends Reloadable {
* @param user the user to retrieve an email for
* @return the email saved for the user, or null if user or email is not present
*/
- DataSourceResult getEmail(String user);
+ DataSourceValue getEmail(String user);
/**
* Return all players of the database.
diff --git a/src/main/java/fr/xephi/authme/datasource/DataSourceResult.java b/src/main/java/fr/xephi/authme/datasource/DataSourceResult.java
deleted file mode 100644
index c005874e2..000000000
--- a/src/main/java/fr/xephi/authme/datasource/DataSourceResult.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package fr.xephi.authme.datasource;
-
-/**
- * Wraps a value and allows to specify whether a value is missing or the player is not registered.
- */
-public final class DataSourceResult {
-
- /** Instance used when a player does not exist. */
- private static final DataSourceResult UNKNOWN_PLAYER = new DataSourceResult<>(null);
- private final T value;
-
- private DataSourceResult(T value) {
- this.value = value;
- }
-
- /**
- * Returns a {@link DataSourceResult} for the given value.
- *
- * @param value the value to wrap
- * @param the value's type
- * @return DataSourceResult object for the given value
- */
- public static DataSourceResult of(T value) {
- return new DataSourceResult<>(value);
- }
-
- /**
- * Returns a {@link DataSourceResult} specifying that the player does not exist.
- *
- * @param the value type
- * @return data source result for unknown player
- */
- public static DataSourceResult unknownPlayer() {
- return UNKNOWN_PLAYER;
- }
-
- /**
- * @return whether the player of the associated value exists
- */
- public boolean playerExists() {
- return this != UNKNOWN_PLAYER;
- }
-
- /**
- * Returns the value. It is {@code null} if the player is unknown. It is also {@code null}
- * if the player exists but does not have the value defined.
- *
- * @return the value, or null
- */
- public T getValue() {
- return value;
- }
-}
diff --git a/src/main/java/fr/xephi/authme/datasource/FlatFile.java b/src/main/java/fr/xephi/authme/datasource/FlatFile.java
index f70b0376f..ab9bf85c1 100644
--- a/src/main/java/fr/xephi/authme/datasource/FlatFile.java
+++ b/src/main/java/fr/xephi/authme/datasource/FlatFile.java
@@ -1,5 +1,6 @@
package fr.xephi.authme.datasource;
+import ch.jalu.datasourcecolumns.data.DataSourceValue;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.data.auth.PlayerAuth;
import fr.xephi.authme.security.crypts.HashedPassword;
@@ -366,7 +367,7 @@ public class FlatFile implements DataSource {
}
@Override
- public DataSourceResult getEmail(String user) {
+ public DataSourceValue getEmail(String user) {
throw new UnsupportedOperationException("Flat file no longer supported");
}
diff --git a/src/main/java/fr/xephi/authme/datasource/MySQL.java b/src/main/java/fr/xephi/authme/datasource/MySQL.java
index 35998330a..3bb187ff1 100644
--- a/src/main/java/fr/xephi/authme/datasource/MySQL.java
+++ b/src/main/java/fr/xephi/authme/datasource/MySQL.java
@@ -5,13 +5,12 @@ import com.zaxxer.hikari.HikariDataSource;
import com.zaxxer.hikari.pool.HikariPool.PoolInitializationException;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.data.auth.PlayerAuth;
+import fr.xephi.authme.datasource.columnshandler.AuthMeColumnsHandler;
import fr.xephi.authme.datasource.mysqlextensions.MySqlExtension;
import fr.xephi.authme.datasource.mysqlextensions.MySqlExtensionsFactory;
-import fr.xephi.authme.security.crypts.HashedPassword;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.properties.DatabaseSettings;
import fr.xephi.authme.settings.properties.HooksSettings;
-import fr.xephi.authme.util.StringUtils;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
@@ -32,7 +31,7 @@ import static fr.xephi.authme.datasource.SqlDataSourceUtils.logSqlException;
* MySQL data source.
*/
@SuppressWarnings({"checkstyle:AbbreviationAsWordInName"}) // Justification: Class name cannot be changed anymore
-public class MySQL implements DataSource {
+public class MySQL extends AbstractSqlDataSource {
private boolean useSsl;
private String host;
@@ -99,6 +98,7 @@ public class MySQL implements DataSource {
this.tableName = settings.getProperty(DatabaseSettings.MYSQL_TABLE);
this.columnOthers = settings.getProperty(HooksSettings.MYSQL_OTHER_USERNAME_COLS);
this.col = new Columns(settings);
+ this.columnsHandler = AuthMeColumnsHandler.createForMySql(this::getConnection, settings);
this.sqlExtension = extensionsFactory.buildExtension(col);
this.poolSize = settings.getProperty(DatabaseSettings.MYSQL_POOL_SIZE);
this.maxLifetime = settings.getProperty(DatabaseSettings.MYSQL_CONNECTION_MAX_LIFETIME);
@@ -267,40 +267,6 @@ public class MySQL implements DataSource {
}
}
- @Override
- public boolean isAuthAvailable(String user) {
- String sql = "SELECT " + col.NAME + " FROM " + tableName + " WHERE " + col.NAME + "=?;";
- try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
- pst.setString(1, user.toLowerCase());
- try (ResultSet rs = pst.executeQuery()) {
- return rs.next();
- }
- } catch (SQLException ex) {
- logSqlException(ex);
- }
- return false;
- }
-
- @Override
- public HashedPassword getPassword(String user) {
- boolean useSalt = !col.SALT.isEmpty();
- String sql = "SELECT " + col.PASSWORD
- + (useSalt ? ", " + col.SALT : "")
- + " FROM " + tableName + " WHERE " + col.NAME + "=?;";
- try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
- pst.setString(1, user.toLowerCase());
- try (ResultSet rs = pst.executeQuery()) {
- if (rs.next()) {
- return new HashedPassword(rs.getString(col.PASSWORD),
- useSalt ? rs.getString(col.SALT) : null);
- }
- }
- } catch (SQLException ex) {
- logSqlException(ex);
- }
- return null;
- }
-
@Override
public PlayerAuth getAuth(String user) {
String sql = "SELECT * FROM " + tableName + " WHERE " + col.NAME + "=?;";
@@ -323,33 +289,9 @@ public class MySQL implements DataSource {
@Override
public boolean saveAuth(PlayerAuth auth) {
+ super.saveAuth(auth);
+
try (Connection con = getConnection()) {
- // TODO ljacqu 20171104: Replace with generic columns util to clean this up
- boolean useSalt = !col.SALT.isEmpty() || !StringUtils.isEmpty(auth.getPassword().getSalt());
- boolean hasEmail = auth.getEmail() != null;
- String emailPlaceholder = hasEmail ? "?" : "DEFAULT";
-
- String sql = "INSERT INTO " + tableName + "("
- + col.NAME + "," + col.PASSWORD + "," + col.REAL_NAME
- + "," + col.EMAIL + "," + col.REGISTRATION_DATE + "," + col.REGISTRATION_IP
- + (useSalt ? "," + col.SALT : "")
- + ") VALUES (?,?,?," + emailPlaceholder + ",?,?" + (useSalt ? ",?" : "") + ");";
- try (PreparedStatement pst = con.prepareStatement(sql)) {
- int index = 1;
- pst.setString(index++, auth.getNickname());
- pst.setString(index++, auth.getPassword().getHash());
- pst.setString(index++, auth.getRealName());
- if (hasEmail) {
- pst.setString(index++, auth.getEmail());
- }
- pst.setObject(index++, auth.getRegistrationDate());
- pst.setString(index++, auth.getRegistrationIp());
- if (useSalt) {
- pst.setString(index++, auth.getPassword().getSalt());
- }
- pst.executeUpdate();
- }
-
if (!columnOthers.isEmpty()) {
for (String column : columnOthers) {
try (PreparedStatement pst = con.prepareStatement(
@@ -369,59 +311,6 @@ public class MySQL implements DataSource {
return false;
}
- @Override
- public boolean updatePassword(PlayerAuth auth) {
- return updatePassword(auth.getNickname(), auth.getPassword());
- }
-
- @Override
- public boolean updatePassword(String user, HashedPassword password) {
- user = user.toLowerCase();
- try (Connection con = getConnection()) {
- boolean useSalt = !col.SALT.isEmpty();
- if (useSalt) {
- String sql = String.format("UPDATE %s SET %s = ?, %s = ? WHERE %s = ?;",
- tableName, col.PASSWORD, col.SALT, col.NAME);
- try (PreparedStatement pst = con.prepareStatement(sql)) {
- pst.setString(1, password.getHash());
- pst.setString(2, password.getSalt());
- pst.setString(3, user);
- pst.executeUpdate();
- }
- } else {
- String sql = String.format("UPDATE %s SET %s = ? WHERE %s = ?;",
- tableName, col.PASSWORD, col.NAME);
- try (PreparedStatement pst = con.prepareStatement(sql)) {
- pst.setString(1, password.getHash());
- pst.setString(2, user);
- pst.executeUpdate();
- }
- }
- sqlExtension.changePassword(user, password, con);
- return true;
- } catch (SQLException ex) {
- logSqlException(ex);
- }
- return false;
- }
-
- @Override
- public boolean updateSession(PlayerAuth auth) {
- String sql = "UPDATE " + tableName + " SET "
- + col.LAST_IP + "=?, " + col.LAST_LOGIN + "=?, " + col.REAL_NAME + "=? WHERE " + col.NAME + "=?;";
- try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
- pst.setString(1, auth.getLastIp());
- pst.setObject(2, auth.getLastLogin());
- pst.setString(3, auth.getRealName());
- pst.setString(4, auth.getNickname());
- pst.executeUpdate();
- return true;
- } catch (SQLException ex) {
- logSqlException(ex);
- }
- return false;
- }
-
@Override
public Set getRecordsToPurge(long until) {
Set list = new HashSet<>();
@@ -459,42 +348,6 @@ public class MySQL implements DataSource {
return false;
}
- @Override
- public boolean updateQuitLoc(PlayerAuth auth) {
- String sql = "UPDATE " + tableName
- + " SET " + col.LASTLOC_X + " =?, " + col.LASTLOC_Y + "=?, " + col.LASTLOC_Z + "=?, "
- + col.LASTLOC_WORLD + "=?, " + col.LASTLOC_YAW + "=?, " + col.LASTLOC_PITCH + "=?"
- + " WHERE " + col.NAME + "=?;";
- try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
- pst.setDouble(1, auth.getQuitLocX());
- pst.setDouble(2, auth.getQuitLocY());
- pst.setDouble(3, auth.getQuitLocZ());
- pst.setString(4, auth.getWorld());
- pst.setFloat(5, auth.getYaw());
- pst.setFloat(6, auth.getPitch());
- pst.setString(7, auth.getNickname());
- pst.executeUpdate();
- return true;
- } catch (SQLException ex) {
- logSqlException(ex);
- }
- return false;
- }
-
- @Override
- public boolean updateEmail(PlayerAuth auth) {
- String sql = "UPDATE " + tableName + " SET " + col.EMAIL + " =? WHERE " + col.NAME + "=?;";
- try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
- pst.setString(1, auth.getEmail());
- pst.setString(2, auth.getNickname());
- pst.executeUpdate();
- return true;
- } catch (SQLException ex) {
- logSqlException(ex);
- }
- return false;
- }
-
@Override
public void closeConnection() {
if (ds != null && !ds.isClosed()) {
@@ -502,39 +355,6 @@ public class MySQL implements DataSource {
}
}
- @Override
- public List getAllAuthsByIp(String ip) {
- List result = new ArrayList<>();
- String sql = "SELECT " + col.NAME + " FROM " + tableName + " WHERE " + col.LAST_IP + "=?;";
- try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
- pst.setString(1, ip);
- try (ResultSet rs = pst.executeQuery()) {
- while (rs.next()) {
- result.add(rs.getString(col.NAME));
- }
- }
- } catch (SQLException ex) {
- logSqlException(ex);
- }
- return result;
- }
-
- @Override
- public int countAuthsByEmail(String email) {
- String sql = "SELECT COUNT(1) FROM " + tableName + " WHERE UPPER(" + col.EMAIL + ") = UPPER(?)";
- try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
- pst.setString(1, email);
- try (ResultSet rs = pst.executeQuery()) {
- if (rs.next()) {
- return rs.getInt(1);
- }
- }
- } catch (SQLException ex) {
- logSqlException(ex);
- }
- return 0;
- }
-
@Override
public void purgeRecords(Collection toPurge) {
String sql = "DELETE FROM " + tableName + " WHERE " + col.NAME + "=?;";
@@ -553,140 +373,6 @@ public class MySQL implements DataSource {
return DataSourceType.MYSQL;
}
- @Override
- public boolean isLogged(String user) {
- String sql = "SELECT " + col.IS_LOGGED + " FROM " + tableName + " WHERE " + col.NAME + "=?;";
- try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
- pst.setString(1, user);
- try (ResultSet rs = pst.executeQuery()) {
- return rs.next() && (rs.getInt(col.IS_LOGGED) == 1);
- }
- } catch (SQLException ex) {
- logSqlException(ex);
- }
- return false;
- }
-
- @Override
- public void setLogged(String user) {
- String sql = "UPDATE " + tableName + " SET " + col.IS_LOGGED + "=? WHERE " + col.NAME + "=?;";
- try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
- pst.setInt(1, 1);
- pst.setString(2, user.toLowerCase());
- pst.executeUpdate();
- } catch (SQLException ex) {
- logSqlException(ex);
- }
- }
-
- @Override
- public void setUnlogged(String user) {
- String sql = "UPDATE " + tableName + " SET " + col.IS_LOGGED + "=? WHERE " + col.NAME + "=?;";
- try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
- pst.setInt(1, 0);
- pst.setString(2, user.toLowerCase());
- pst.executeUpdate();
- } catch (SQLException ex) {
- logSqlException(ex);
- }
- }
-
- @Override
- public boolean hasSession(String user) {
- String sql = "SELECT " + col.HAS_SESSION + " FROM " + tableName + " WHERE " + col.NAME + "=?;";
- try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
- pst.setString(1, user.toLowerCase());
- try (ResultSet rs = pst.executeQuery()) {
- return rs.next() && (rs.getInt(col.HAS_SESSION) == 1);
- }
- } catch (SQLException ex) {
- logSqlException(ex);
- }
- return false;
- }
-
- @Override
- public void grantSession(String user) {
- String sql = "UPDATE " + tableName + " SET " + col.HAS_SESSION + "=? WHERE " + col.NAME + "=?;";
- try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
- pst.setInt(1, 1);
- pst.setString(2, user.toLowerCase());
- pst.executeUpdate();
- } catch (SQLException ex) {
- logSqlException(ex);
- }
- }
-
- @Override
- public void revokeSession(String user) {
- String sql = "UPDATE " + tableName + " SET " + col.HAS_SESSION + "=? WHERE " + col.NAME + "=?;";
- try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
- pst.setInt(1, 0);
- pst.setString(2, user.toLowerCase());
- pst.executeUpdate();
- } catch (SQLException ex) {
- logSqlException(ex);
- }
- }
-
- @Override
- public void purgeLogged() {
- String sql = "UPDATE " + tableName + " SET " + col.IS_LOGGED + "=? WHERE " + col.IS_LOGGED + "=?;";
- try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
- pst.setInt(1, 0);
- pst.setInt(2, 1);
- pst.executeUpdate();
- } catch (SQLException ex) {
- logSqlException(ex);
- }
- }
-
- @Override
- public int getAccountsRegistered() {
- int result = 0;
- String sql = "SELECT COUNT(*) FROM " + tableName;
- try (Connection con = getConnection();
- Statement st = con.createStatement();
- ResultSet rs = st.executeQuery(sql)) {
- if (rs.next()) {
- result = rs.getInt(1);
- }
- } catch (SQLException ex) {
- logSqlException(ex);
- }
- return result;
- }
-
- @Override
- public boolean updateRealName(String user, String realName) {
- String sql = "UPDATE " + tableName + " SET " + col.REAL_NAME + "=? WHERE " + col.NAME + "=?;";
- try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
- pst.setString(1, realName);
- pst.setString(2, user);
- pst.executeUpdate();
- return true;
- } catch (SQLException ex) {
- logSqlException(ex);
- }
- return false;
- }
-
- @Override
- public DataSourceResult getEmail(String user) {
- String sql = "SELECT " + col.EMAIL + " FROM " + tableName + " WHERE " + col.NAME + "=?;";
- try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
- pst.setString(1, user);
- try (ResultSet rs = pst.executeQuery()) {
- if (rs.next()) {
- return DataSourceResult.of(rs.getString(1));
- }
- }
- } catch (SQLException ex) {
- logSqlException(ex);
- }
- return DataSourceResult.unknownPlayer();
- }
-
@Override
public List getAllAuths() {
List auths = new ArrayList<>();
diff --git a/src/main/java/fr/xephi/authme/datasource/SQLite.java b/src/main/java/fr/xephi/authme/datasource/SQLite.java
index 2978a93f8..ff72a8018 100644
--- a/src/main/java/fr/xephi/authme/datasource/SQLite.java
+++ b/src/main/java/fr/xephi/authme/datasource/SQLite.java
@@ -3,10 +3,9 @@ package fr.xephi.authme.datasource;
import com.google.common.annotations.VisibleForTesting;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.data.auth.PlayerAuth;
-import fr.xephi.authme.security.crypts.HashedPassword;
+import fr.xephi.authme.datasource.columnshandler.AuthMeColumnsHandler;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.properties.DatabaseSettings;
-import fr.xephi.authme.util.StringUtils;
import java.io.File;
import java.sql.Connection;
@@ -29,7 +28,7 @@ import static fr.xephi.authme.datasource.SqlDataSourceUtils.logSqlException;
* SQLite data source.
*/
@SuppressWarnings({"checkstyle:AbbreviationAsWordInName"}) // Justification: Class name cannot be changed anymore
-public class SQLite implements DataSource {
+public class SQLite extends AbstractSqlDataSource {
private final Settings settings;
private final File dataFolder;
@@ -71,6 +70,7 @@ public class SQLite implements DataSource {
this.tableName = settings.getProperty(DatabaseSettings.MYSQL_TABLE);
this.col = new Columns(settings);
this.con = connection;
+ this.columnsHandler = AuthMeColumnsHandler.createForSqlite(con, settings);
}
/**
@@ -85,6 +85,7 @@ public class SQLite implements DataSource {
ConsoleLogger.debug("SQLite driver loaded");
this.con = DriverManager.getConnection("jdbc:sqlite:plugins/AuthMe/" + database + ".db");
+ this.columnsHandler = AuthMeColumnsHandler.createForSqlite(con, settings);
}
/**
@@ -209,40 +210,6 @@ public class SQLite implements DataSource {
}
}
- @Override
- public boolean isAuthAvailable(String user) {
- String sql = "SELECT 1 FROM " + tableName + " WHERE LOWER(" + col.NAME + ")=LOWER(?);";
- try (PreparedStatement pst = con.prepareStatement(sql)) {
- pst.setString(1, user);
- try (ResultSet rs = pst.executeQuery()) {
- return rs.next();
- }
- } catch (SQLException ex) {
- ConsoleLogger.warning(ex.getMessage());
- return false;
- }
- }
-
- @Override
- public HashedPassword getPassword(String user) {
- boolean useSalt = !col.SALT.isEmpty();
- String sql = "SELECT " + col.PASSWORD
- + (useSalt ? ", " + col.SALT : "")
- + " FROM " + tableName + " WHERE " + col.NAME + "=?";
- try (PreparedStatement pst = con.prepareStatement(sql)) {
- pst.setString(1, user);
- try (ResultSet rs = pst.executeQuery()) {
- if (rs.next()) {
- return new HashedPassword(rs.getString(col.PASSWORD),
- useSalt ? rs.getString(col.SALT) : null);
- }
- }
- } catch (SQLException ex) {
- logSqlException(ex);
- }
- return null;
- }
-
@Override
public PlayerAuth getAuth(String user) {
String sql = "SELECT * FROM " + tableName + " WHERE LOWER(" + col.NAME + ")=LOWER(?);";
@@ -259,95 +226,6 @@ public class SQLite implements DataSource {
return null;
}
- @Override
- public boolean saveAuth(PlayerAuth auth) {
- PreparedStatement pst = null;
- try {
- HashedPassword password = auth.getPassword();
- if (col.SALT.isEmpty()) {
- if (!StringUtils.isEmpty(auth.getPassword().getSalt())) {
- ConsoleLogger.warning("Warning! Detected hashed password with separate salt but the salt column "
- + "is not set in the config!");
- }
-
- pst = con.prepareStatement("INSERT INTO " + tableName + "(" + col.NAME + "," + col.PASSWORD
- + "," + col.REAL_NAME + "," + col.EMAIL
- + "," + col.REGISTRATION_DATE + "," + col.REGISTRATION_IP
- + ") VALUES (?,?,?,?,?,?);");
- pst.setString(1, auth.getNickname());
- pst.setString(2, password.getHash());
- pst.setString(3, auth.getRealName());
- pst.setString(4, auth.getEmail());
- pst.setLong(5, auth.getRegistrationDate());
- pst.setString(6, auth.getRegistrationIp());
- pst.executeUpdate();
- } else {
- pst = con.prepareStatement("INSERT INTO " + tableName + "(" + col.NAME + "," + col.PASSWORD
- + "," + col.REAL_NAME + "," + col.EMAIL
- + "," + col.REGISTRATION_DATE + "," + col.REGISTRATION_IP + "," + col.SALT
- + ") VALUES (?,?,?,?,?,?,?);");
- pst.setString(1, auth.getNickname());
- pst.setString(2, password.getHash());
- pst.setString(3, auth.getRealName());
- pst.setString(4, auth.getEmail());
- pst.setLong(5, auth.getRegistrationDate());
- pst.setString(6, auth.getRegistrationIp());
- pst.setString(7, password.getSalt());
- pst.executeUpdate();
- }
- } catch (SQLException ex) {
- logSqlException(ex);
- } finally {
- close(pst);
- }
- return true;
- }
-
- @Override
- public boolean updatePassword(PlayerAuth auth) {
- return updatePassword(auth.getNickname(), auth.getPassword());
- }
-
- @Override
- public boolean updatePassword(String user, HashedPassword password) {
- user = user.toLowerCase();
- boolean useSalt = !col.SALT.isEmpty();
- String sql = "UPDATE " + tableName + " SET " + col.PASSWORD + " = ?"
- + (useSalt ? ", " + col.SALT + " = ?" : "")
- + " WHERE " + col.NAME + " = ?";
- try (PreparedStatement pst = con.prepareStatement(sql)){
- pst.setString(1, password.getHash());
- if (useSalt) {
- pst.setString(2, password.getSalt());
- pst.setString(3, user);
- } else {
- pst.setString(2, user);
- }
- pst.executeUpdate();
- return true;
- } catch (SQLException ex) {
- logSqlException(ex);
- }
- return false;
- }
-
- @Override
- public boolean updateSession(PlayerAuth auth) {
- String sql = "UPDATE " + tableName + " SET " + col.LAST_IP + "=?, " + col.LAST_LOGIN + "=?, "
- + col.REAL_NAME + "=? WHERE " + col.NAME + "=?;";
- try (PreparedStatement pst = con.prepareStatement(sql)){
- pst.setString(1, auth.getLastIp());
- pst.setObject(2, auth.getLastLogin());
- pst.setString(3, auth.getRealName());
- pst.setString(4, auth.getNickname());
- pst.executeUpdate();
- return true;
- } catch (SQLException ex) {
- logSqlException(ex);
- }
- return false;
- }
-
@Override
public Set getRecordsToPurge(long until) {
Set list = new HashSet<>();
@@ -395,42 +273,6 @@ public class SQLite implements DataSource {
return false;
}
- @Override
- public boolean updateQuitLoc(PlayerAuth auth) {
- String sql = "UPDATE " + tableName + " SET "
- + col.LASTLOC_X + "=?, " + col.LASTLOC_Y + "=?, " + col.LASTLOC_Z + "=?, "
- + col.LASTLOC_WORLD + "=?, " + col.LASTLOC_YAW + "=?, " + col.LASTLOC_PITCH + "=? "
- + "WHERE " + col.NAME + "=?;";
- try (PreparedStatement pst = con.prepareStatement(sql)) {
- pst.setDouble(1, auth.getQuitLocX());
- pst.setDouble(2, auth.getQuitLocY());
- pst.setDouble(3, auth.getQuitLocZ());
- pst.setString(4, auth.getWorld());
- pst.setFloat(5, auth.getYaw());
- pst.setFloat(6, auth.getPitch());
- pst.setString(7, auth.getNickname());
- pst.executeUpdate();
- return true;
- } catch (SQLException ex) {
- logSqlException(ex);
- }
- return false;
- }
-
- @Override
- public boolean updateEmail(PlayerAuth auth) {
- String sql = "UPDATE " + tableName + " SET " + col.EMAIL + "=? WHERE " + col.NAME + "=?;";
- try (PreparedStatement pst = con.prepareStatement(sql)) {
- pst.setString(1, auth.getEmail());
- pst.setString(2, auth.getNickname());
- pst.executeUpdate();
- return true;
- } catch (SQLException ex) {
- logSqlException(ex);
- }
- return false;
- }
-
@Override
public void closeConnection() {
try {
@@ -442,180 +284,11 @@ public class SQLite implements DataSource {
}
}
- @Override
- public List getAllAuthsByIp(String ip) {
- List countIp = new ArrayList<>();
- String sql = "SELECT " + col.NAME + " FROM " + tableName + " WHERE " + col.LAST_IP + "=?;";
- try (PreparedStatement pst = con.prepareStatement(sql)) {
- pst.setString(1, ip);
- try (ResultSet rs = pst.executeQuery()) {
- while (rs.next()) {
- countIp.add(rs.getString(col.NAME));
- }
- return countIp;
- }
- } catch (SQLException ex) {
- logSqlException(ex);
- }
- return new ArrayList<>();
- }
-
- @Override
- public int countAuthsByEmail(String email) {
- String sql = "SELECT COUNT(1) FROM " + tableName + " WHERE " + col.EMAIL + " = ? COLLATE NOCASE;";
- try (PreparedStatement pst = con.prepareStatement(sql)) {
- pst.setString(1, email);
- try (ResultSet rs = pst.executeQuery()) {
- if (rs.next()) {
- return rs.getInt(1);
- }
- }
- } catch (SQLException ex) {
- logSqlException(ex);
- }
- return 0;
- }
-
@Override
public DataSourceType getType() {
return DataSourceType.SQLITE;
}
- @Override
- public boolean isLogged(String user) {
- String sql = "SELECT " + col.IS_LOGGED + " FROM " + tableName + " WHERE LOWER(" + col.NAME + ")=?;";
- try (PreparedStatement pst = con.prepareStatement(sql)) {
- pst.setString(1, user);
- try (ResultSet rs = pst.executeQuery()) {
- if (rs.next()) {
- return rs.getInt(col.IS_LOGGED) == 1;
- }
- }
- } catch (SQLException ex) {
- logSqlException(ex);
- }
- return false;
- }
-
- @Override
- public void setLogged(String user) {
- String sql = "UPDATE " + tableName + " SET " + col.IS_LOGGED + "=? WHERE LOWER(" + col.NAME + ")=?;";
- try (PreparedStatement pst = con.prepareStatement(sql)) {
- pst.setInt(1, 1);
- pst.setString(2, user);
- pst.executeUpdate();
- } catch (SQLException ex) {
- logSqlException(ex);
- }
- }
-
- @Override
- public void setUnlogged(String user) {
- String sql = "UPDATE " + tableName + " SET " + col.IS_LOGGED + "=? WHERE LOWER(" + col.NAME + ")=?;";
- try (PreparedStatement pst = con.prepareStatement(sql)) {
- pst.setInt(1, 0);
- pst.setString(2, user);
- pst.executeUpdate();
- } catch (SQLException ex) {
- logSqlException(ex);
- }
- }
-
- @Override
- public boolean hasSession(String user) {
- String sql = "SELECT " + col.HAS_SESSION + " FROM " + tableName + " WHERE LOWER(" + col.NAME + ")=?;";
- try (PreparedStatement pst = con.prepareStatement(sql)) {
- pst.setString(1, user.toLowerCase());
- try (ResultSet rs = pst.executeQuery()) {
- if (rs.next()) {
- return rs.getInt(col.HAS_SESSION) == 1;
- }
- }
- } catch (SQLException ex) {
- logSqlException(ex);
- }
- return false;
- }
-
- @Override
- public void grantSession(String user) {
- String sql = "UPDATE " + tableName + " SET " + col.HAS_SESSION + "=? WHERE LOWER(" + col.NAME + ")=?;";
- try (PreparedStatement pst = con.prepareStatement(sql)) {
- pst.setInt(1, 1);
- pst.setString(2, user.toLowerCase());
- pst.executeUpdate();
- } catch (SQLException ex) {
- logSqlException(ex);
- }
- }
-
- @Override
- public void revokeSession(String user) {
- String sql = "UPDATE " + tableName + " SET " + col.HAS_SESSION + "=? WHERE LOWER(" + col.NAME + ")=?;";
- try (PreparedStatement pst = con.prepareStatement(sql)) {
- pst.setInt(1, 0);
- pst.setString(2, user.toLowerCase());
- pst.executeUpdate();
- } catch (SQLException ex) {
- logSqlException(ex);
- }
- }
-
- @Override
- public void purgeLogged() {
- String sql = "UPDATE " + tableName + " SET " + col.IS_LOGGED + "=? WHERE " + col.IS_LOGGED + "=?;";
- try (PreparedStatement pst = con.prepareStatement(sql)) {
- pst.setInt(1, 0);
- pst.setInt(2, 1);
- pst.executeUpdate();
- } catch (SQLException ex) {
- logSqlException(ex);
- }
- }
-
- @Override
- public int getAccountsRegistered() {
- 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);
- }
- return 0;
- }
-
- @Override
- public boolean updateRealName(String user, String realName) {
- String sql = "UPDATE " + tableName + " SET " + col.REAL_NAME + "=? WHERE " + col.NAME + "=?;";
- try (PreparedStatement pst = con.prepareStatement(sql)) {
- pst.setString(1, realName);
- pst.setString(2, user);
- pst.executeUpdate();
- return true;
- } catch (SQLException ex) {
- logSqlException(ex);
- }
- return false;
- }
-
- @Override
- public DataSourceResult getEmail(String user) {
- String sql = "SELECT " + col.EMAIL + " FROM " + tableName + " WHERE " + col.NAME + "=?;";
- try (PreparedStatement pst = con.prepareStatement(sql)) {
- pst.setString(1, user);
- try (ResultSet rs = pst.executeQuery()) {
- if (rs.next()) {
- return DataSourceResult.of(rs.getString(1));
- }
- }
- } catch (SQLException ex) {
- logSqlException(ex);
- }
- return DataSourceResult.unknownPlayer();
- }
-
@Override
public List getAllAuths() {
List auths = new ArrayList<>();
@@ -716,16 +389,6 @@ public class SQLite implements DataSource {
+ currentTimestamp + ", to all " + updatedRows + " rows");
}
- private static void close(Statement st) {
- if (st != null) {
- try {
- st.close();
- } catch (SQLException ex) {
- logSqlException(ex);
- }
- }
- }
-
private static void close(Connection con) {
if (con != null) {
try {
diff --git a/src/main/java/fr/xephi/authme/datasource/columnshandler/AuthMeColumns.java b/src/main/java/fr/xephi/authme/datasource/columnshandler/AuthMeColumns.java
new file mode 100644
index 000000000..5c235095f
--- /dev/null
+++ b/src/main/java/fr/xephi/authme/datasource/columnshandler/AuthMeColumns.java
@@ -0,0 +1,82 @@
+package fr.xephi.authme.datasource.columnshandler;
+
+import fr.xephi.authme.data.auth.PlayerAuth;
+import fr.xephi.authme.settings.properties.DatabaseSettings;
+
+import static fr.xephi.authme.datasource.columnshandler.AuthMeColumnsFactory.ColumnOptions.DEFAULT_FOR_NULL;
+import static fr.xephi.authme.datasource.columnshandler.AuthMeColumnsFactory.ColumnOptions.OPTIONAL;
+import static fr.xephi.authme.datasource.columnshandler.AuthMeColumnsFactory.createDouble;
+import static fr.xephi.authme.datasource.columnshandler.AuthMeColumnsFactory.createFloat;
+import static fr.xephi.authme.datasource.columnshandler.AuthMeColumnsFactory.createInteger;
+import static fr.xephi.authme.datasource.columnshandler.AuthMeColumnsFactory.createLong;
+import static fr.xephi.authme.datasource.columnshandler.AuthMeColumnsFactory.createString;
+
+/**
+ * Contains column definitions for the AuthMe table.
+ */
+public final class AuthMeColumns {
+
+ public static final PlayerAuthColumn NAME = createString(
+ DatabaseSettings.MYSQL_COL_NAME, PlayerAuth::getNickname);
+
+ public static final PlayerAuthColumn NICK_NAME = createString(
+ DatabaseSettings.MYSQL_COL_REALNAME, PlayerAuth::getRealName);
+
+ public static final PlayerAuthColumn PASSWORD = createString(
+ DatabaseSettings.MYSQL_COL_PASSWORD, auth -> auth.getPassword().getHash());
+
+ public static final PlayerAuthColumn SALT = createString(
+ DatabaseSettings.MYSQL_COL_SALT, auth -> auth.getPassword().getSalt(), OPTIONAL);
+
+ public static final PlayerAuthColumn EMAIL = createString(
+ DatabaseSettings.MYSQL_COL_EMAIL, PlayerAuth::getEmail, DEFAULT_FOR_NULL);
+
+ public static final PlayerAuthColumn LAST_IP = createString(
+ DatabaseSettings.MYSQL_COL_LAST_IP, PlayerAuth::getLastIp);
+
+ public static final PlayerAuthColumn GROUP_ID = createInteger(
+ DatabaseSettings.MYSQL_COL_GROUP, PlayerAuth::getGroupId, OPTIONAL);
+
+ public static final PlayerAuthColumn LAST_LOGIN = createLong(
+ DatabaseSettings.MYSQL_COL_LASTLOGIN, PlayerAuth::getLastLogin);
+
+ public static final PlayerAuthColumn REGISTRATION_IP = createString(
+ DatabaseSettings.MYSQL_COL_REGISTER_IP, PlayerAuth::getRegistrationIp);
+
+ public static final PlayerAuthColumn REGISTRATION_DATE = createLong(
+ DatabaseSettings.MYSQL_COL_REGISTER_DATE, PlayerAuth::getRegistrationDate);
+
+ // --------
+ // Location columns
+ // --------
+ public static final PlayerAuthColumn LOCATION_X = createDouble(
+ DatabaseSettings.MYSQL_COL_LASTLOC_X, PlayerAuth::getQuitLocX);
+
+ public static final PlayerAuthColumn LOCATION_Y = createDouble(
+ DatabaseSettings.MYSQL_COL_LASTLOC_Y, PlayerAuth::getQuitLocY);
+
+ public static final PlayerAuthColumn LOCATION_Z = createDouble(
+ DatabaseSettings.MYSQL_COL_LASTLOC_Z, PlayerAuth::getQuitLocZ);
+
+ public static final PlayerAuthColumn LOCATION_WORLD = createString(
+ DatabaseSettings.MYSQL_COL_LASTLOC_WORLD, PlayerAuth::getWorld);
+
+ public static final PlayerAuthColumn LOCATION_YAW = createFloat(
+ DatabaseSettings.MYSQL_COL_LASTLOC_YAW, PlayerAuth::getYaw);
+
+ public static final PlayerAuthColumn LOCATION_PITCH = createFloat(
+ DatabaseSettings.MYSQL_COL_LASTLOC_PITCH, PlayerAuth::getPitch);
+
+ // --------
+ // Columns not on PlayerAuth
+ // --------
+ public static final DataSourceColumn IS_LOGGED = createInteger(
+ DatabaseSettings.MYSQL_COL_ISLOGGED);
+
+ public static final DataSourceColumn HAS_SESSION = createInteger(
+ DatabaseSettings.MYSQL_COL_HASSESSION);
+
+
+ private AuthMeColumns() {
+ }
+}
diff --git a/src/main/java/fr/xephi/authme/datasource/columnshandler/AuthMeColumnsFactory.java b/src/main/java/fr/xephi/authme/datasource/columnshandler/AuthMeColumnsFactory.java
new file mode 100644
index 000000000..3400f76cd
--- /dev/null
+++ b/src/main/java/fr/xephi/authme/datasource/columnshandler/AuthMeColumnsFactory.java
@@ -0,0 +1,83 @@
+package fr.xephi.authme.datasource.columnshandler;
+
+import ch.jalu.configme.properties.Property;
+import ch.jalu.datasourcecolumns.ColumnType;
+import ch.jalu.datasourcecolumns.StandardTypes;
+import fr.xephi.authme.data.auth.PlayerAuth;
+
+import java.util.function.Function;
+
+/**
+ * Util class for initializing {@link DataSourceColumn} objects.
+ */
+final class AuthMeColumnsFactory {
+
+ private AuthMeColumnsFactory() {
+ }
+
+ static DataSourceColumn createInteger(Property nameProperty,
+ ColumnOptions... options) {
+ return new DataSourceColumn<>(StandardTypes.INTEGER, nameProperty,
+ isOptional(options), hasDefaultForNull(options));
+ }
+
+ static PlayerAuthColumn createInteger(Property nameProperty,
+ Function playerAuthGetter,
+ ColumnOptions... options) {
+ return createInternal(StandardTypes.INTEGER, nameProperty, playerAuthGetter, options);
+ }
+
+ static PlayerAuthColumn createLong(Property nameProperty,
+ Function playerAuthGetter,
+ ColumnOptions... options) {
+ return createInternal(StandardTypes.LONG, nameProperty, playerAuthGetter, options);
+ }
+
+ static PlayerAuthColumn createString(Property nameProperty,
+ Function playerAuthGetter,
+ ColumnOptions... options) {
+ return createInternal(StandardTypes.STRING, nameProperty, playerAuthGetter, options);
+ }
+
+ static PlayerAuthColumn createDouble(Property nameProperty,
+ Function playerAuthGetter,
+ ColumnOptions... options) {
+ return createInternal(StandardTypes.DOUBLE, nameProperty, playerAuthGetter, options);
+ }
+
+ static PlayerAuthColumn createFloat(Property nameProperty,
+ Function playerAuthGetter,
+ ColumnOptions... options) {
+ return createInternal(StandardTypes.FLOAT, nameProperty, playerAuthGetter, options);
+ }
+
+ private static PlayerAuthColumn createInternal(ColumnType type, Property nameProperty,
+ Function authGetter,
+ ColumnOptions... options) {
+ return new PlayerAuthColumn<>(type, nameProperty, isOptional(options), hasDefaultForNull(options), authGetter);
+ }
+
+ private static boolean isOptional(ColumnOptions[] options) {
+ return containsInArray(ColumnOptions.OPTIONAL, options);
+ }
+
+ private static boolean hasDefaultForNull(ColumnOptions[] options) {
+ return containsInArray(ColumnOptions.DEFAULT_FOR_NULL, options);
+ }
+
+ private static boolean containsInArray(ColumnOptions needle, ColumnOptions[] haystack) {
+ for (ColumnOptions option : haystack) {
+ if (option == needle) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ enum ColumnOptions {
+
+ OPTIONAL,
+
+ DEFAULT_FOR_NULL
+ }
+}
diff --git a/src/main/java/fr/xephi/authme/datasource/columnshandler/AuthMeColumnsHandler.java b/src/main/java/fr/xephi/authme/datasource/columnshandler/AuthMeColumnsHandler.java
new file mode 100644
index 000000000..bb0d80b77
--- /dev/null
+++ b/src/main/java/fr/xephi/authme/datasource/columnshandler/AuthMeColumnsHandler.java
@@ -0,0 +1,205 @@
+package fr.xephi.authme.datasource.columnshandler;
+
+import ch.jalu.datasourcecolumns.data.DataSourceValue;
+import ch.jalu.datasourcecolumns.data.DataSourceValues;
+import ch.jalu.datasourcecolumns.data.UpdateValues;
+import ch.jalu.datasourcecolumns.predicate.Predicate;
+import ch.jalu.datasourcecolumns.sqlimplementation.PredicateSqlGenerator;
+import ch.jalu.datasourcecolumns.sqlimplementation.PreparedStatementGenerator;
+import ch.jalu.datasourcecolumns.sqlimplementation.ResultSetValueRetriever;
+import ch.jalu.datasourcecolumns.sqlimplementation.SqlColumnsHandler;
+import fr.xephi.authme.data.auth.PlayerAuth;
+import fr.xephi.authme.settings.Settings;
+import fr.xephi.authme.settings.properties.DatabaseSettings;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.List;
+
+import static fr.xephi.authme.datasource.SqlDataSourceUtils.logSqlException;
+
+/**
+ * Wrapper of {@link SqlColumnsHandler} for the AuthMe data table.
+ * Wraps exceptions and provides better support for operations based on a {@link PlayerAuth} object.
+ */
+public final class AuthMeColumnsHandler {
+
+ private final SqlColumnsHandler internalHandler;
+
+ private AuthMeColumnsHandler(SqlColumnsHandler internalHandler) {
+ this.internalHandler = internalHandler;
+ }
+
+ /**
+ * Creates a column handler for SQLite.
+ *
+ * @param connection the connection to the database
+ * @param settings plugin settings
+ * @return created column handler
+ */
+ public static AuthMeColumnsHandler createForSqlite(Connection connection, Settings settings) {
+ ColumnContext columnContext = new ColumnContext(settings, false);
+ String tableName = settings.getProperty(DatabaseSettings.MYSQL_TABLE);
+ String nameColumn = settings.getProperty(DatabaseSettings.MYSQL_COL_NAME);
+
+ SqlColumnsHandler sqlColHandler = new SqlColumnsHandler<>(
+ PreparedStatementGenerator.fromConnection(connection), columnContext, tableName, nameColumn,
+ new ResultSetValueRetriever<>(columnContext), new PredicateSqlGenerator<>(columnContext, true));
+ return new AuthMeColumnsHandler(sqlColHandler);
+ }
+
+ /**
+ * Creates a column handler for MySQL.
+ *
+ * @param connectionSupplier supplier of connections from the connection pool
+ * @param settings plugin settings
+ * @return created column handler
+ */
+ public static AuthMeColumnsHandler createForMySql(ConnectionSupplier connectionSupplier, Settings settings) {
+ ColumnContext columnContext = new ColumnContext(settings, true);
+ String tableName = settings.getProperty(DatabaseSettings.MYSQL_TABLE);
+ String nameColumn = settings.getProperty(DatabaseSettings.MYSQL_COL_NAME);
+
+ SqlColumnsHandler sqlColHandler = new SqlColumnsHandler<>(
+ new MySqlPreparedStatementGenerator(connectionSupplier), columnContext, tableName, nameColumn,
+ new ResultSetValueRetriever<>(columnContext), new PredicateSqlGenerator<>(columnContext));
+ return new AuthMeColumnsHandler(sqlColHandler);
+ }
+
+ /**
+ * Changes a column from a specific row to the given value.
+ *
+ * @param name name of the account to modify
+ * @param column the column to modify
+ * @param value the value to set the column to
+ * @param the column type
+ * @return true upon success, false otherwise
+ */
+ public boolean update(String name, DataSourceColumn column, T value) {
+ try {
+ return internalHandler.update(name, column, value);
+ } catch (SQLException e) {
+ logSqlException(e);
+ return false;
+ }
+ }
+
+ /**
+ * Updates a row to have the values as retrieved from the PlayerAuth object.
+ *
+ * @param auth the player auth object to modify and to get values from
+ * @param columns the columns to update in the row
+ * @return true upon success, false otherwise
+ */
+ public boolean update(PlayerAuth auth, PlayerAuthColumn>... columns) {
+ try {
+ return internalHandler.update(auth.getNickname(), auth, columns);
+ } catch (SQLException e) {
+ logSqlException(e);
+ return false;
+ }
+ }
+
+ /**
+ * Updates a row to have the given values.
+ *
+ * @param name the name of the account to modify
+ * @param updateValues the values to set on the row
+ * @return true upon success, false otherwise
+ */
+ public boolean update(String name, UpdateValues updateValues) {
+ try {
+ return internalHandler.update(name.toLowerCase(), updateValues);
+ } catch (SQLException e) {
+ logSqlException(e);
+ return false;
+ }
+ }
+
+ /**
+ * Sets the given value to the provided column for all rows which match the predicate.
+ *
+ * @param predicate the predicate to filter rows by
+ * @param column the column to modify on the matched rows
+ * @param value the new value to set
+ * @param the column type
+ * @return number of modified rows
+ */
+ public int update(Predicate predicate, DataSourceColumn column, T value) {
+ try {
+ return internalHandler.update(predicate, column, value);
+ } catch (SQLException e) {
+ logSqlException(e);
+ return 0;
+ }
+ }
+
+ /**
+ * Retrieves the given column from a given row.
+ *
+ * @param name the account name to look up
+ * @param column the column whose value should be retrieved
+ * @param the column type
+ * @return the result of the lookup
+ * @throws SQLException .
+ */
+ public DataSourceValue retrieve(String name, DataSourceColumn column) throws SQLException {
+ return internalHandler.retrieve(name.toLowerCase(), column);
+ }
+
+ /**
+ * Retrieves multiple values from a given row.
+ *
+ * @param name the account name to look up
+ * @param columns the columns to retrieve
+ * @return map-like object with the requested values
+ * @throws SQLException .
+ */
+ public DataSourceValues retrieve(String name, DataSourceColumn>... columns) throws SQLException {
+ return internalHandler.retrieve(name.toLowerCase(), columns);
+ }
+
+ /**
+ * Retrieves a column's value for all rows that satisfy the given predicate.
+ *
+ * @param predicate the predicate to fulfill
+ * @param column the column to retrieve from the matching rows
+ * @param the column's value type
+ * @return the values of the matching rows
+ * @throws SQLException .
+ */
+ public List retrieve(Predicate predicate, DataSourceColumn column) throws SQLException {
+ return internalHandler.retrieve(predicate, column);
+ }
+
+ /**
+ * Inserts the given values into a new row, as taken from the player auth.
+ *
+ * @param auth the player auth to get values from
+ * @param columns the columns to insert
+ * @return true upon success, false otherwise
+ */
+ public boolean insert(PlayerAuth auth, PlayerAuthColumn>... columns) {
+ try {
+ return internalHandler.insert(auth, columns);
+ } catch (SQLException e) {
+ logSqlException(e);
+ return false;
+ }
+ }
+
+ /**
+ * Returns the number of rows that match the provided predicate.
+ *
+ * @param predicate the predicate to test the rows for
+ * @return number of rows fulfilling the predicate
+ */
+ public int count(Predicate predicate) {
+ try {
+ return internalHandler.count(predicate);
+ } catch (SQLException e) {
+ logSqlException(e);
+ return 0;
+ }
+ }
+}
diff --git a/src/main/java/fr/xephi/authme/datasource/columnshandler/ColumnContext.java b/src/main/java/fr/xephi/authme/datasource/columnshandler/ColumnContext.java
new file mode 100644
index 000000000..554266a05
--- /dev/null
+++ b/src/main/java/fr/xephi/authme/datasource/columnshandler/ColumnContext.java
@@ -0,0 +1,35 @@
+package fr.xephi.authme.datasource.columnshandler;
+
+import fr.xephi.authme.settings.Settings;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Context for resolving the properties of {@link AuthMeColumns} entries.
+ */
+public class ColumnContext {
+
+ private final Settings settings;
+ private final Map, String> columnNames = new HashMap<>();
+ private final boolean hasDefaultSupport;
+
+ /**
+ * Constructor.
+ *
+ * @param settings plugin settings
+ * @param hasDefaultSupport whether or not the underlying database has support for the {@code DEFAULT} keyword
+ */
+ public ColumnContext(Settings settings, boolean hasDefaultSupport) {
+ this.settings = settings;
+ this.hasDefaultSupport = hasDefaultSupport;
+ }
+
+ public String getName(DataSourceColumn> column) {
+ return columnNames.computeIfAbsent(column, k -> settings.getProperty(k.getNameProperty()));
+ }
+
+ public boolean hasDefaultSupport() {
+ return hasDefaultSupport;
+ }
+}
diff --git a/src/main/java/fr/xephi/authme/datasource/columnshandler/ConnectionSupplier.java b/src/main/java/fr/xephi/authme/datasource/columnshandler/ConnectionSupplier.java
new file mode 100644
index 000000000..77fbe8f3a
--- /dev/null
+++ b/src/main/java/fr/xephi/authme/datasource/columnshandler/ConnectionSupplier.java
@@ -0,0 +1,20 @@
+package fr.xephi.authme.datasource.columnshandler;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+
+/**
+ * Supplier of connections to a database.
+ */
+@FunctionalInterface
+public interface ConnectionSupplier {
+
+ /**
+ * Returns a connection to the database.
+ *
+ * @return the connection
+ * @throws SQLException .
+ */
+ Connection get() throws SQLException;
+
+}
diff --git a/src/main/java/fr/xephi/authme/datasource/columnshandler/DataSourceColumn.java b/src/main/java/fr/xephi/authme/datasource/columnshandler/DataSourceColumn.java
new file mode 100644
index 000000000..4b7fa4ca7
--- /dev/null
+++ b/src/main/java/fr/xephi/authme/datasource/columnshandler/DataSourceColumn.java
@@ -0,0 +1,57 @@
+package fr.xephi.authme.datasource.columnshandler;
+
+import ch.jalu.configme.properties.Property;
+import ch.jalu.datasourcecolumns.Column;
+import ch.jalu.datasourcecolumns.ColumnType;
+
+/**
+ * Basic {@link Column} implementation for AuthMe.
+ *
+ * @param column type
+ */
+public class DataSourceColumn implements Column {
+
+ private final ColumnType columnType;
+ private final Property nameProperty;
+ private final boolean isOptional;
+ private final boolean useDefaultForNull;
+
+ /**
+ * Constructor.
+ *
+ * @param type type of the column
+ * @param nameProperty property defining the column name
+ * @param isOptional whether or not the column can be skipped (if name is configured to empty string)
+ * @param useDefaultForNull whether SQL DEFAULT should be used for null values (if supported by the database)
+ */
+ DataSourceColumn(ColumnType type, Property nameProperty, boolean isOptional, boolean useDefaultForNull) {
+ this.columnType = type;
+ this.nameProperty = nameProperty;
+ this.isOptional = isOptional;
+ this.useDefaultForNull = useDefaultForNull;
+ }
+
+ public Property getNameProperty() {
+ return nameProperty;
+ }
+
+ @Override
+ public String resolveName(ColumnContext columnContext) {
+ return columnContext.getName(this);
+ }
+
+ @Override
+ public ColumnType getType() {
+ return columnType;
+ }
+
+ @Override
+ public boolean isColumnUsed(ColumnContext columnContext) {
+ return !isOptional || !resolveName(columnContext).isEmpty();
+ }
+
+ @Override
+ public boolean useDefaultForNullValue(ColumnContext columnContext) {
+ return useDefaultForNull && columnContext.hasDefaultSupport();
+ }
+}
diff --git a/src/main/java/fr/xephi/authme/datasource/columnshandler/MySqlPreparedStatementGenerator.java b/src/main/java/fr/xephi/authme/datasource/columnshandler/MySqlPreparedStatementGenerator.java
new file mode 100644
index 000000000..c20357ae4
--- /dev/null
+++ b/src/main/java/fr/xephi/authme/datasource/columnshandler/MySqlPreparedStatementGenerator.java
@@ -0,0 +1,44 @@
+package fr.xephi.authme.datasource.columnshandler;
+
+import ch.jalu.datasourcecolumns.sqlimplementation.PreparedStatementGenerator;
+import ch.jalu.datasourcecolumns.sqlimplementation.PreparedStatementResult;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+
+/**
+ * Implementation of {@link PreparedStatementGenerator} for MySQL which ensures that the connection
+ * taken from the connection pool is also closed after the prepared statement has been executed.
+ */
+class MySqlPreparedStatementGenerator implements PreparedStatementGenerator {
+
+ private final ConnectionSupplier connectionSupplier;
+
+ MySqlPreparedStatementGenerator(ConnectionSupplier connectionSupplier) {
+ this.connectionSupplier = connectionSupplier;
+ }
+
+ @Override
+ public PreparedStatementResult create(String sql) throws SQLException {
+ Connection connection = connectionSupplier.get();
+ return new MySqlPreparedStatementResult(connection, connection.prepareStatement(sql));
+ }
+
+ /** Prepared statement result which also closes the associated connection. */
+ private static final class MySqlPreparedStatementResult extends PreparedStatementResult {
+
+ private final Connection connection;
+
+ MySqlPreparedStatementResult(Connection connection, PreparedStatement preparedStatement) {
+ super(preparedStatement);
+ this.connection = connection;
+ }
+
+ @Override
+ public void close() throws SQLException {
+ super.close();
+ connection.close();
+ }
+ }
+}
diff --git a/src/main/java/fr/xephi/authme/datasource/columnshandler/PlayerAuthColumn.java b/src/main/java/fr/xephi/authme/datasource/columnshandler/PlayerAuthColumn.java
new file mode 100644
index 000000000..43d022b13
--- /dev/null
+++ b/src/main/java/fr/xephi/authme/datasource/columnshandler/PlayerAuthColumn.java
@@ -0,0 +1,32 @@
+package fr.xephi.authme.datasource.columnshandler;
+
+import ch.jalu.configme.properties.Property;
+import ch.jalu.datasourcecolumns.ColumnType;
+import ch.jalu.datasourcecolumns.DependentColumn;
+import fr.xephi.authme.data.auth.PlayerAuth;
+
+import java.util.function.Function;
+
+/**
+ * Implementation for columns which can also be retrieved from a {@link PlayerAuth} object.
+ *
+ * @param column type
+ */
+public class PlayerAuthColumn extends DataSourceColumn implements DependentColumn {
+
+ private final Function playerAuthGetter;
+
+ /*
+ * Constructor. See parent class for details.
+ */
+ PlayerAuthColumn(ColumnType type, Property nameProperty, boolean isOptional, boolean useDefaultForNull,
+ Function playerAuthGetter) {
+ super(type, nameProperty, isOptional, useDefaultForNull);
+ this.playerAuthGetter = playerAuthGetter;
+ }
+
+ @Override
+ public T getValueFromDependent(PlayerAuth auth) {
+ return playerAuthGetter.apply(auth);
+ }
+}
diff --git a/src/main/resources/messages/messages_pl.yml b/src/main/resources/messages/messages_pl.yml
index 4d9061dfd..cc512acc3 100644
--- a/src/main/resources/messages/messages_pl.yml
+++ b/src/main/resources/messages/messages_pl.yml
@@ -79,7 +79,7 @@ on_join_validation:
country_banned: '&4Ten kraj jest zbanowany na tym serwerze'
not_owner_error: '&cNie jesteś właścicielem tego konta, wybierz inny nick!'
invalid_name_case: '&cPowinieneś dołączyć do serwera z nicku %valid, a nie %invalid.'
- # TODO quick_command: 'You used a command too fast! Please, join the server again and wait more before using any command.'
+ quick_command: '&cUżyłeś komendy zbyt szybko! Ponownie dołącz do serwera i poczekaj chwilę, zanim użyjesz dowolnej komendy.'
# Email
email:
diff --git a/src/test/java/fr/xephi/authme/ClassesConsistencyTest.java b/src/test/java/fr/xephi/authme/ClassesConsistencyTest.java
index 267f7d7cb..f02b5dc9b 100644
--- a/src/test/java/fr/xephi/authme/ClassesConsistencyTest.java
+++ b/src/test/java/fr/xephi/authme/ClassesConsistencyTest.java
@@ -5,7 +5,10 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import fr.xephi.authme.data.captcha.CaptchaCodeStorage;
+import fr.xephi.authme.datasource.AbstractSqlDataSource;
import fr.xephi.authme.datasource.Columns;
+import fr.xephi.authme.datasource.columnshandler.DataSourceColumn;
+import fr.xephi.authme.datasource.columnshandler.PlayerAuthColumn;
import fr.xephi.authme.datasource.mysqlextensions.MySqlExtension;
import fr.xephi.authme.initialization.HasCleanup;
import fr.xephi.authme.process.register.executors.RegistrationMethod;
@@ -52,7 +55,7 @@ public class ClassesConsistencyTest {
int.class, long.class, float.class, String.class, File.class, Enum.class, collectionsUnmodifiableList(),
Charset.class,
/* AuthMe */
- Property.class, RegistrationMethod.class,
+ Property.class, RegistrationMethod.class, DataSourceColumn.class, PlayerAuthColumn.class,
/* Guava */
ImmutableMap.class, ImmutableList.class);
@@ -60,6 +63,7 @@ public class ClassesConsistencyTest {
private static final Set> CLASSES_EXCLUDED_FROM_VISIBILITY_TEST = ImmutableSet.of(
Whirlpool.class, // not our implementation, so we don't touch it
MySqlExtension.class, // has immutable protected fields used by all children
+ AbstractSqlDataSource.class, // protected members for inheritance
Columns.class // uses non-static String constants, which is safe
);
diff --git a/src/test/java/fr/xephi/authme/command/executable/authme/GetEmailCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/authme/GetEmailCommandTest.java
index 07c92d13c..dc3fda40e 100644
--- a/src/test/java/fr/xephi/authme/command/executable/authme/GetEmailCommandTest.java
+++ b/src/test/java/fr/xephi/authme/command/executable/authme/GetEmailCommandTest.java
@@ -1,7 +1,7 @@
package fr.xephi.authme.command.executable.authme;
+import ch.jalu.datasourcecolumns.data.DataSourceValueImpl;
import fr.xephi.authme.datasource.DataSource;
-import fr.xephi.authme.datasource.DataSourceResult;
import fr.xephi.authme.message.MessageKey;
import fr.xephi.authme.service.CommonService;
import org.bukkit.command.CommandSender;
@@ -38,7 +38,7 @@ public class GetEmailCommandTest {
public void shouldReportUnknownUser() {
// given
String user = "myTestUser";
- given(dataSource.getEmail(user)).willReturn(DataSourceResult.unknownPlayer());
+ given(dataSource.getEmail(user)).willReturn(DataSourceValueImpl.unknownRow());
CommandSender sender = mock(CommandSender.class);
// when
@@ -53,7 +53,7 @@ public class GetEmailCommandTest {
// given
String user = "userToView";
String email = "user.email@example.org";
- given(dataSource.getEmail(user)).willReturn(DataSourceResult.of(email));
+ given(dataSource.getEmail(user)).willReturn(DataSourceValueImpl.of(email));
CommandSender sender = mock(CommandSender.class);
// when
diff --git a/src/test/java/fr/xephi/authme/command/executable/email/RecoverEmailCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/email/RecoverEmailCommandTest.java
index 416649e05..5842ec300 100644
--- a/src/test/java/fr/xephi/authme/command/executable/email/RecoverEmailCommandTest.java
+++ b/src/test/java/fr/xephi/authme/command/executable/email/RecoverEmailCommandTest.java
@@ -1,12 +1,12 @@
package fr.xephi.authme.command.executable.email;
+import ch.jalu.datasourcecolumns.data.DataSourceValueImpl;
import ch.jalu.injector.testing.BeforeInjecting;
import ch.jalu.injector.testing.DelayedInjectionRunner;
import ch.jalu.injector.testing.InjectDelayed;
import fr.xephi.authme.TestHelper;
import fr.xephi.authme.data.auth.PlayerCache;
import fr.xephi.authme.datasource.DataSource;
-import fr.xephi.authme.datasource.DataSourceResult;
import fr.xephi.authme.mail.EmailService;
import fr.xephi.authme.message.MessageKey;
import fr.xephi.authme.security.PasswordSecurity;
@@ -118,7 +118,7 @@ public class RecoverEmailCommandTest {
given(sender.getName()).willReturn(name);
given(emailService.hasAllInformation()).willReturn(true);
given(playerCache.isAuthenticated(name)).willReturn(false);
- given(dataSource.getEmail(name)).willReturn(DataSourceResult.unknownPlayer());
+ given(dataSource.getEmail(name)).willReturn(DataSourceValueImpl.unknownRow());
// when
command.executeCommand(sender, Collections.singletonList("someone@example.com"));
@@ -138,7 +138,7 @@ public class RecoverEmailCommandTest {
given(sender.getName()).willReturn(name);
given(emailService.hasAllInformation()).willReturn(true);
given(playerCache.isAuthenticated(name)).willReturn(false);
- given(dataSource.getEmail(name)).willReturn(DataSourceResult.of(DEFAULT_EMAIL));
+ given(dataSource.getEmail(name)).willReturn(DataSourceValueImpl.of(DEFAULT_EMAIL));
// when
command.executeCommand(sender, Collections.singletonList(DEFAULT_EMAIL));
@@ -158,7 +158,7 @@ public class RecoverEmailCommandTest {
given(sender.getName()).willReturn(name);
given(emailService.hasAllInformation()).willReturn(true);
given(playerCache.isAuthenticated(name)).willReturn(false);
- given(dataSource.getEmail(name)).willReturn(DataSourceResult.of("raptor@example.org"));
+ given(dataSource.getEmail(name)).willReturn(DataSourceValueImpl.of("raptor@example.org"));
// when
command.executeCommand(sender, Collections.singletonList("wrong-email@example.com"));
@@ -180,7 +180,7 @@ public class RecoverEmailCommandTest {
given(emailService.sendRecoveryCode(anyString(), anyString(), anyString())).willReturn(true);
given(playerCache.isAuthenticated(name)).willReturn(false);
String email = "v@example.com";
- given(dataSource.getEmail(name)).willReturn(DataSourceResult.of(email));
+ given(dataSource.getEmail(name)).willReturn(DataSourceValueImpl.of(email));
String code = "a94f37";
given(recoveryCodeService.isRecoveryCodeNeeded()).willReturn(true);
given(recoveryCodeService.generateCode(name)).willReturn(code);
@@ -205,7 +205,7 @@ public class RecoverEmailCommandTest {
given(emailService.sendPasswordMail(anyString(), anyString(), anyString())).willReturn(true);
given(playerCache.isAuthenticated(name)).willReturn(false);
String email = "vulture@example.com";
- given(dataSource.getEmail(name)).willReturn(DataSourceResult.of(email));
+ given(dataSource.getEmail(name)).willReturn(DataSourceValueImpl.of(email));
given(recoveryCodeService.isRecoveryCodeNeeded()).willReturn(false);
setBukkitServiceToRunTaskAsynchronously(bukkitService);
diff --git a/src/test/java/fr/xephi/authme/data/VerificationCodeManagerTest.java b/src/test/java/fr/xephi/authme/data/VerificationCodeManagerTest.java
index b99d6a373..732b1ad70 100644
--- a/src/test/java/fr/xephi/authme/data/VerificationCodeManagerTest.java
+++ b/src/test/java/fr/xephi/authme/data/VerificationCodeManagerTest.java
@@ -1,7 +1,7 @@
package fr.xephi.authme.data;
+import ch.jalu.datasourcecolumns.data.DataSourceValueImpl;
import fr.xephi.authme.datasource.DataSource;
-import fr.xephi.authme.datasource.DataSourceResult;
import fr.xephi.authme.mail.EmailService;
import fr.xephi.authme.permission.PermissionsManager;
import fr.xephi.authme.permission.PlayerPermission;
@@ -51,7 +51,7 @@ public class VerificationCodeManagerTest {
// given
String name1 = "ILoveTests";
Player player1 = mockPlayerWithName(name1);
- given(dataSource.getEmail(name1)).willReturn(DataSourceResult.of("ilovetests@test.com"));
+ given(dataSource.getEmail(name1)).willReturn(DataSourceValueImpl.of("ilovetests@test.com"));
given(permissionsManager.hasPermission(player1, PlayerPermission.VERIFICATION_CODE)).willReturn(true);
String name2 = "StillLovingTests";
Player player2 = mockPlayerWithName(name2);
@@ -106,7 +106,7 @@ public class VerificationCodeManagerTest {
// given
String player = "ILoveTests";
String email = "ilovetests@test.com";
- given(dataSource.getEmail(player)).willReturn(DataSourceResult.of(email));
+ given(dataSource.getEmail(player)).willReturn(DataSourceValueImpl.of(email));
VerificationCodeManager codeManager1 = createCodeManager();
VerificationCodeManager codeManager2 = createCodeManager();
codeManager2.codeExistOrGenerateNew(player);
@@ -125,7 +125,7 @@ public class VerificationCodeManagerTest {
// given
String player = "ILoveTests";
String email = "ilovetests@test.com";
- given(dataSource.getEmail(player)).willReturn(DataSourceResult.of(email));
+ given(dataSource.getEmail(player)).willReturn(DataSourceValueImpl.of(email));
VerificationCodeManager codeManager1 = createCodeManager();
VerificationCodeManager codeManager2 = createCodeManager();
codeManager2.codeExistOrGenerateNew(player);
@@ -145,7 +145,7 @@ public class VerificationCodeManagerTest {
String player = "ILoveTests";
String code = "193458";
String email = "ilovetests@test.com";
- given(dataSource.getEmail(player)).willReturn(DataSourceResult.of(email));
+ given(dataSource.getEmail(player)).willReturn(DataSourceValueImpl.of(email));
VerificationCodeManager codeManager1 = createCodeManager();
VerificationCodeManager codeManager2 = createCodeManager();
codeManager1.codeExistOrGenerateNew(player);
diff --git a/src/test/java/fr/xephi/authme/datasource/AbstractDataSourceIntegrationTest.java b/src/test/java/fr/xephi/authme/datasource/AbstractDataSourceIntegrationTest.java
index 0e8094825..58fd59c08 100644
--- a/src/test/java/fr/xephi/authme/datasource/AbstractDataSourceIntegrationTest.java
+++ b/src/test/java/fr/xephi/authme/datasource/AbstractDataSourceIntegrationTest.java
@@ -1,5 +1,7 @@
package fr.xephi.authme.datasource;
+import ch.jalu.datasourcecolumns.data.DataSourceValue;
+import ch.jalu.datasourcecolumns.data.DataSourceValueImpl;
import com.google.common.collect.Lists;
import fr.xephi.authme.data.auth.PlayerAuth;
import fr.xephi.authme.security.crypts.HashedPassword;
@@ -61,7 +63,7 @@ public abstract class AbstractDataSourceIntegrationTest {
// when
HashedPassword bobbyPassword = dataSource.getPassword("bobby");
HashedPassword invalidPassword = dataSource.getPassword("doesNotExist");
- HashedPassword userPassword = dataSource.getPassword("user");
+ HashedPassword userPassword = dataSource.getPassword("User");
// then
assertThat(bobbyPassword, equalToHash("$SHA$11aa0706173d7272$dbba966"));
@@ -162,7 +164,8 @@ public abstract class AbstractDataSourceIntegrationTest {
boolean response2 = dataSource.updatePassword("non-existent-name", new HashedPassword("sd"));
// then
- assertThat(response1 && response2, equalTo(true));
+ assertThat(response1, equalTo(true));
+ assertThat(response2, equalTo(false)); // no record modified
assertThat(dataSource.getPassword("user"), equalToHash(newHash));
}
@@ -177,7 +180,8 @@ public abstract class AbstractDataSourceIntegrationTest {
boolean response2 = dataSource.updatePassword("non-existent-name", new HashedPassword("asdfasdf", "a1f34ec"));
// then
- assertThat(response1 && response2, equalTo(true));
+ assertThat(response1, equalTo(true));
+ assertThat(response2, equalTo(false)); // no record modified
assertThat(dataSource.getPassword("user"), equalToHash("new_hash"));
}
@@ -193,7 +197,8 @@ public abstract class AbstractDataSourceIntegrationTest {
boolean response2 = dataSource.updatePassword(invalidAuth);
// then
- assertThat(response1 && response2, equalTo(true));
+ assertThat(response1, equalTo(true));
+ assertThat(response2, equalTo(false)); // no record modified
assertThat(dataSource.getPassword("bobby"), equalToHash("tt", "cc"));
}
@@ -275,7 +280,8 @@ public abstract class AbstractDataSourceIntegrationTest {
boolean response2 = dataSource.updateEmail(invalidAuth);
// then
- assertThat(response1 && response2, equalTo(true));
+ assertThat(response1, equalTo(true));
+ assertThat(response2, equalTo(false)); // no record modified
assertThat(dataSource.getAllAuths(), hasItem(hasAuthBasicData("user", "user", email, "34.56.78.90")));
}
@@ -330,7 +336,8 @@ public abstract class AbstractDataSourceIntegrationTest {
boolean response2 = dataSource.updateRealName("notExists", "NOTEXISTS");
// then
- assertThat(response1 && response2, equalTo(true));
+ assertThat(response1, equalTo(true));
+ assertThat(response2, equalTo(false)); // no record modified
assertThat(dataSource.getAuth("bobby"), hasAuthBasicData("bobby", "BOBBY", null, "123.45.67.89"));
}
@@ -417,12 +424,12 @@ public abstract class AbstractDataSourceIntegrationTest {
DataSource dataSource = getDataSource();
// when
- DataSourceResult email1 = dataSource.getEmail(user1);
- DataSourceResult email2 = dataSource.getEmail(user2);
+ DataSourceValue email1 = dataSource.getEmail(user1);
+ DataSourceValue email2 = dataSource.getEmail(user2);
// then
assertThat(email1.getValue(), equalTo("user@example.org"));
- assertThat(email2, is(DataSourceResult.unknownPlayer()));
+ assertThat(email2, is(DataSourceValueImpl.unknownRow()));
}
@Test
diff --git a/src/test/java/fr/xephi/authme/datasource/MySqlIntegrationTest.java b/src/test/java/fr/xephi/authme/datasource/MySqlIntegrationTest.java
index eab6a4cc4..027608230 100644
--- a/src/test/java/fr/xephi/authme/datasource/MySqlIntegrationTest.java
+++ b/src/test/java/fr/xephi/authme/datasource/MySqlIntegrationTest.java
@@ -55,7 +55,9 @@ public class MySqlIntegrationTest extends AbstractDataSourceIntegrationTest {
HikariConfig config = new HikariConfig();
config.setDataSourceClassName("org.h2.jdbcx.JdbcDataSource");
config.setConnectionTestQuery("VALUES 1");
- config.addDataSourceProperty("URL", "jdbc:h2:mem:test");
+ // Note "ignorecase=true": H2 does not support `COLLATE NOCASE` for case-insensitive equals queries.
+ // MySQL is by default case-insensitive so this is OK to make as an assumption.
+ config.addDataSourceProperty("URL", "jdbc:h2:mem:test;ignorecase=true");
config.addDataSourceProperty("user", "sa");
config.addDataSourceProperty("password", "sa");
HikariDataSource ds = new HikariDataSource(config);