From 5a58f2c44f918b1378a6de4b5862f496b1a68219 Mon Sep 17 00:00:00 2001 From: ljacqu Date: Sat, 24 Mar 2018 12:24:25 +0100 Subject: [PATCH 01/10] #1539 Integrate data source columns library - Create wrapper around SqlColumnsHandler for AuthMe-specific behavior - Integrate columns handler into first SQLite and MySQL method implementations --- pom.xml | 8 + .../authme/datasource/AuthMeColumns.java | 125 ++++++++++++++++ .../authme/datasource/ColumnContext.java | 20 +++ .../fr/xephi/authme/datasource/MySQL.java | 98 +++--------- .../fr/xephi/authme/datasource/SQLite.java | 89 +++-------- .../columnshandler/AuthMeColumnsHandler.java | 141 ++++++++++++++++++ .../xephi/authme/ClassesConsistencyTest.java | 3 +- .../AbstractDataSourceIntegrationTest.java | 17 ++- 8 files changed, 346 insertions(+), 155 deletions(-) create mode 100644 src/main/java/fr/xephi/authme/datasource/AuthMeColumns.java create mode 100644 src/main/java/fr/xephi/authme/datasource/ColumnContext.java create mode 100644 src/main/java/fr/xephi/authme/datasource/columnshandler/AuthMeColumnsHandler.java diff --git a/pom.xml b/pom.xml index 0ee1ecf65..f109d7411 100644 --- a/pom.xml +++ b/pom.xml @@ -788,6 +788,14 @@ + + ch.jalu + datasourcecolumns + 0.1-SNAPSHOT + compile + true + + diff --git a/src/main/java/fr/xephi/authme/datasource/AuthMeColumns.java b/src/main/java/fr/xephi/authme/datasource/AuthMeColumns.java new file mode 100644 index 000000000..657084aea --- /dev/null +++ b/src/main/java/fr/xephi/authme/datasource/AuthMeColumns.java @@ -0,0 +1,125 @@ +package fr.xephi.authme.datasource; + +import ch.jalu.configme.properties.Property; +import ch.jalu.datasourcecolumns.ColumnType; +import ch.jalu.datasourcecolumns.DependentColumn; +import ch.jalu.datasourcecolumns.StandardTypes; +import fr.xephi.authme.data.auth.PlayerAuth; +import fr.xephi.authme.settings.properties.DatabaseSettings; + +import java.util.function.Function; + +public final class AuthMeColumns implements DependentColumn { + + public static final AuthMeColumns NAME = createString( + DatabaseSettings.MYSQL_COL_NAME, PlayerAuth::getNickname); + + public static final AuthMeColumns NICK_NAME = createString( + DatabaseSettings.MYSQL_COL_REALNAME, PlayerAuth::getRealName); + + public static final AuthMeColumns PASSWORD = createString( + DatabaseSettings.MYSQL_COL_PASSWORD, auth -> auth.getPassword().getHash()); + + public static final AuthMeColumns SALT = new AuthMeColumns<>( + StandardTypes.STRING, DatabaseSettings.MYSQL_COL_SALT, auth -> auth.getPassword().getSalt(), true); + + public static final AuthMeColumns EMAIL = createString( + DatabaseSettings.MYSQL_COL_EMAIL, PlayerAuth::getEmail); + + public static final AuthMeColumns LAST_IP = createString( + DatabaseSettings.MYSQL_COL_LAST_IP, PlayerAuth::getLastIp); + + public static final AuthMeColumns LOCATION_X = createDouble( + DatabaseSettings.MYSQL_COL_LASTLOC_X, PlayerAuth::getQuitLocX); + + public static final AuthMeColumns LOCATION_Y = createDouble( + DatabaseSettings.MYSQL_COL_LASTLOC_Y, PlayerAuth::getQuitLocY); + + public static final AuthMeColumns LOCATION_Z = createDouble( + DatabaseSettings.MYSQL_COL_LASTLOC_Z, PlayerAuth::getQuitLocZ); + + public static final AuthMeColumns LOCATION_WORLD = createString( + DatabaseSettings.MYSQL_COL_LASTLOC_WORLD, PlayerAuth::getWorld); + + public static final AuthMeColumns LOCATION_YAW = createFloat( + DatabaseSettings.MYSQL_COL_LASTLOC_YAW, PlayerAuth::getYaw); + + public static final AuthMeColumns LOCATION_PITCH = createFloat( + DatabaseSettings.MYSQL_COL_LASTLOC_PITCH, PlayerAuth::getPitch); + + + private final ColumnType columnType; + private final Property nameProperty; + private final Function playerAuthGetter; + private final boolean isOptional; + + private AuthMeColumns(ColumnType type, Property nameProperty, Function playerAuthGetter, + boolean isOptional) { + this.columnType = type; + this.nameProperty = nameProperty; + this.playerAuthGetter = playerAuthGetter; + this.isOptional = isOptional; + } + + private static AuthMeColumns createString(Property nameProperty, + Function getter) { + return new AuthMeColumns<>(StandardTypes.STRING, nameProperty, getter, false); + } + + private static AuthMeColumns createDouble(Property nameProperty, + Function getter) { + return new AuthMeColumns<>(new DoubleType(), nameProperty, getter, false); + } + + private static AuthMeColumns createFloat(Property nameProperty, + Function getter) { + return new AuthMeColumns<>(new FloatType(), nameProperty, getter, false); + } + + + public Property getNameProperty() { + return nameProperty; + } + + @Override + public T getValueFromDependent(PlayerAuth playerAuth) { + return playerAuthGetter.apply(playerAuth); + } + + @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 false; + } + + // TODO: Move this to the project... + private static final class DoubleType implements ColumnType { + + @Override + public Class getClazz() { + return Double.class; + } + } + + private static final class FloatType implements ColumnType { + + @Override + public Class getClazz() { + return Float.class; + } + } +} diff --git a/src/main/java/fr/xephi/authme/datasource/ColumnContext.java b/src/main/java/fr/xephi/authme/datasource/ColumnContext.java new file mode 100644 index 000000000..cbc743fad --- /dev/null +++ b/src/main/java/fr/xephi/authme/datasource/ColumnContext.java @@ -0,0 +1,20 @@ +package fr.xephi.authme.datasource; + +import fr.xephi.authme.settings.Settings; + +import java.util.HashMap; +import java.util.Map; + +public class ColumnContext { + + private final Settings settings; + private final Map, String> columnNames = new HashMap<>(); + + public ColumnContext(Settings settings) { + this.settings = settings; + } + + public String getName(AuthMeColumns column) { + return columnNames.computeIfAbsent(column, k -> settings.getProperty(k.getNameProperty())); + } +} diff --git a/src/main/java/fr/xephi/authme/datasource/MySQL.java b/src/main/java/fr/xephi/authme/datasource/MySQL.java index ce46baadd..f098d4683 100644 --- a/src/main/java/fr/xephi/authme/datasource/MySQL.java +++ b/src/main/java/fr/xephi/authme/datasource/MySQL.java @@ -1,10 +1,12 @@ package fr.xephi.authme.datasource; +import ch.jalu.datasourcecolumns.data.DataSourceValues; import com.google.common.annotations.VisibleForTesting; 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; @@ -25,6 +27,7 @@ import java.util.HashSet; import java.util.List; import java.util.Set; +import static ch.jalu.datasourcecolumns.data.UpdateValues.with; import static fr.xephi.authme.datasource.SqlDataSourceUtils.getNullableLong; import static fr.xephi.authme.datasource.SqlDataSourceUtils.logSqlException; @@ -45,6 +48,7 @@ public class MySQL implements DataSource { private int maxLifetime; private List columnOthers; private Columns col; + private AuthMeColumnsHandler columnsHandler; private MySqlExtension sqlExtension; private HikariDataSource ds; @@ -99,6 +103,8 @@ 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(sql -> getConnection().prepareStatement(sql), settings); this.sqlExtension = extensionsFactory.buildExtension(col); this.poolSize = settings.getProperty(DatabaseSettings.MYSQL_POOL_SIZE); this.maxLifetime = settings.getProperty(DatabaseSettings.MYSQL_CONNECTION_MAX_LIFETIME); @@ -278,20 +284,13 @@ public class MySQL implements DataSource { @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); - } + try { + DataSourceValues passwordResult = columnsHandler.retrieve(user, AuthMeColumns.PASSWORD, AuthMeColumns.SALT); + if (passwordResult.rowExists()) { + return new HashedPassword(passwordResult.get(AuthMeColumns.PASSWORD), passwordResult.get(AuthMeColumns.SALT)); } - } catch (SQLException ex) { - logSqlException(ex); + } catch (SQLException e) { + logSqlException(e); } return null; } @@ -371,33 +370,9 @@ public class MySQL implements DataSource { @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; + return columnsHandler.update(user, + with(AuthMeColumns.PASSWORD, password.getHash()) + .and(AuthMeColumns.SALT, password.getSalt()).build()); } @Override @@ -456,38 +431,14 @@ public class MySQL implements DataSource { @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; + return columnsHandler.update(auth, + AuthMeColumns.LOCATION_X, AuthMeColumns.LOCATION_Y, AuthMeColumns.LOCATION_Z, + AuthMeColumns.LOCATION_WORLD, AuthMeColumns.LOCATION_YAW, AuthMeColumns.LOCATION_PITCH); } @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; + return columnsHandler.update(auth, AuthMeColumns.EMAIL); } @Override @@ -654,16 +605,7 @@ public class MySQL implements DataSource { @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; + return columnsHandler.update(user, AuthMeColumns.NICK_NAME, realName); } @Override diff --git a/src/main/java/fr/xephi/authme/datasource/SQLite.java b/src/main/java/fr/xephi/authme/datasource/SQLite.java index ada94afbc..57d12a6b4 100644 --- a/src/main/java/fr/xephi/authme/datasource/SQLite.java +++ b/src/main/java/fr/xephi/authme/datasource/SQLite.java @@ -1,8 +1,10 @@ package fr.xephi.authme.datasource; +import ch.jalu.datasourcecolumns.data.DataSourceValues; import com.google.common.annotations.VisibleForTesting; import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.data.auth.PlayerAuth; +import fr.xephi.authme.datasource.columnshandler.AuthMeColumnsHandler; import fr.xephi.authme.security.crypts.HashedPassword; import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.properties.DatabaseSettings; @@ -22,6 +24,7 @@ import java.util.HashSet; import java.util.List; import java.util.Set; +import static ch.jalu.datasourcecolumns.data.UpdateValues.with; import static fr.xephi.authme.datasource.SqlDataSourceUtils.getNullableLong; import static fr.xephi.authme.datasource.SqlDataSourceUtils.logSqlException; @@ -37,6 +40,7 @@ public class SQLite implements DataSource { private final String tableName; private final Columns col; private Connection con; + private AuthMeColumnsHandler columnsHandler; /** * Constructor for SQLite. @@ -71,6 +75,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); } /** @@ -220,20 +225,13 @@ public class SQLite implements DataSource { @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); - } + 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 ex) { - logSqlException(ex); + } catch (SQLException e) { + logSqlException(e); } return null; } @@ -305,25 +303,9 @@ public class SQLite implements DataSource { @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; + return columnsHandler.update(user, + with(AuthMeColumns.PASSWORD, password.getHash()) + .and(AuthMeColumns.SALT, password.getSalt()).build()); } @Override @@ -392,38 +374,14 @@ public class SQLite implements DataSource { @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; + return columnsHandler.update(auth, + AuthMeColumns.LOCATION_X, AuthMeColumns.LOCATION_Y, AuthMeColumns.LOCATION_Z, + AuthMeColumns.LOCATION_WORLD, AuthMeColumns.LOCATION_YAW, AuthMeColumns.LOCATION_PITCH); } @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; + return columnsHandler.update(auth, AuthMeColumns.EMAIL); } @Override @@ -583,16 +541,7 @@ public class SQLite implements DataSource { @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; + return columnsHandler.update(user, AuthMeColumns.NICK_NAME, realName); } @Override 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..b4c02dc93 --- /dev/null +++ b/src/main/java/fr/xephi/authme/datasource/columnshandler/AuthMeColumnsHandler.java @@ -0,0 +1,141 @@ +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.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.datasource.AuthMeColumns; +import fr.xephi.authme.datasource.ColumnContext; +import fr.xephi.authme.settings.Settings; +import fr.xephi.authme.settings.properties.DatabaseSettings; + +import java.sql.Connection; +import java.sql.SQLException; + +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); + String tableName = settings.getProperty(DatabaseSettings.MYSQL_TABLE); + String nameColumn = settings.getProperty(DatabaseSettings.MYSQL_COL_NAME); + + SqlColumnsHandler sqlColHandler = + new SqlColumnsHandler<>(connection, columnContext, tableName, nameColumn); + return new AuthMeColumnsHandler(sqlColHandler); + } + + /** + * Creates a column handler for MySQL. + * + * @param preparedStatementGenerator supplier of SQL prepared statements with a connection to the database + * @param settings plugin settings + * @return created column handler + */ + public static AuthMeColumnsHandler createForMySql(PreparedStatementGenerator preparedStatementGenerator, + Settings settings) { + ColumnContext columnContext = new ColumnContext(settings); + String tableName = settings.getProperty(DatabaseSettings.MYSQL_TABLE); + String nameColumn = settings.getProperty(DatabaseSettings.MYSQL_COL_NAME); + + SqlColumnsHandler sqlColHandler = new SqlColumnsHandler<>(preparedStatementGenerator, + 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, AuthMeColumns 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, AuthMeColumns... 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; + } + } + + /** + * 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 + */ + public DataSourceValue retrieve(String name, AuthMeColumns 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 + */ + public DataSourceValues retrieve(String name, AuthMeColumns... columns) throws SQLException { + return internalHandler.retrieve(name.toLowerCase(), columns); + } +} diff --git a/src/test/java/fr/xephi/authme/ClassesConsistencyTest.java b/src/test/java/fr/xephi/authme/ClassesConsistencyTest.java index 267f7d7cb..4005dc798 100644 --- a/src/test/java/fr/xephi/authme/ClassesConsistencyTest.java +++ b/src/test/java/fr/xephi/authme/ClassesConsistencyTest.java @@ -5,6 +5,7 @@ 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.AuthMeColumns; import fr.xephi.authme.datasource.Columns; import fr.xephi.authme.datasource.mysqlextensions.MySqlExtension; import fr.xephi.authme.initialization.HasCleanup; @@ -52,7 +53,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, AuthMeColumns.class, /* Guava */ ImmutableMap.class, ImmutableList.class); diff --git a/src/test/java/fr/xephi/authme/datasource/AbstractDataSourceIntegrationTest.java b/src/test/java/fr/xephi/authme/datasource/AbstractDataSourceIntegrationTest.java index 530ab56be..70df2d48b 100644 --- a/src/test/java/fr/xephi/authme/datasource/AbstractDataSourceIntegrationTest.java +++ b/src/test/java/fr/xephi/authme/datasource/AbstractDataSourceIntegrationTest.java @@ -61,7 +61,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")); @@ -160,7 +160,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)); } @@ -175,7 +176,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")); } @@ -191,7 +193,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")); } @@ -273,7 +276,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"))); } @@ -328,7 +332,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")); } From 837bfb7935e069e53f9ba8a3dffc4e09c8b724e1 Mon Sep 17 00:00:00 2001 From: Gabriele C Date: Sat, 24 Mar 2018 15:47:40 +0100 Subject: [PATCH 02/10] Update dependencies --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 0ee1ecf65..b6b1d4ec2 100644 --- a/pom.xml +++ b/pom.xml @@ -395,7 +395,7 @@ com.google.guava guava - 24.0-jre + 24.1-jre true @@ -808,7 +808,7 @@ org.mockito mockito-core test - 2.15.0 + 2.16.0 hamcrest-core From 881ef6a640c86f27ac63da65ffc897124ef2f7ce Mon Sep 17 00:00:00 2001 From: ljacqu Date: Sat, 24 Mar 2018 21:16:43 +0100 Subject: [PATCH 03/10] #1539 DataSource columns: close MySQL connections, add missing columns, use newly built-in types, improve column initialization --- .../authme/datasource/ColumnContext.java | 20 ----- .../fr/xephi/authme/datasource/MySQL.java | 35 ++------- .../fr/xephi/authme/datasource/SQLite.java | 45 +---------- .../{ => columnshandler}/AuthMeColumns.java | 72 ++++++++---------- .../columnshandler/AuthMeColumnsFactory.java | 76 +++++++++++++++++++ .../columnshandler/AuthMeColumnsHandler.java | 34 ++++++--- .../columnshandler/ColumnContext.java | 35 +++++++++ .../columnshandler/ConnectionSupplier.java | 17 +++++ .../MySqlPreparedStatementGenerator.java | 44 +++++++++++ .../xephi/authme/ClassesConsistencyTest.java | 2 +- 10 files changed, 238 insertions(+), 142 deletions(-) delete mode 100644 src/main/java/fr/xephi/authme/datasource/ColumnContext.java rename src/main/java/fr/xephi/authme/datasource/{ => columnshandler}/AuthMeColumns.java (61%) create mode 100644 src/main/java/fr/xephi/authme/datasource/columnshandler/AuthMeColumnsFactory.java create mode 100644 src/main/java/fr/xephi/authme/datasource/columnshandler/ColumnContext.java create mode 100644 src/main/java/fr/xephi/authme/datasource/columnshandler/ConnectionSupplier.java create mode 100644 src/main/java/fr/xephi/authme/datasource/columnshandler/MySqlPreparedStatementGenerator.java diff --git a/src/main/java/fr/xephi/authme/datasource/ColumnContext.java b/src/main/java/fr/xephi/authme/datasource/ColumnContext.java deleted file mode 100644 index cbc743fad..000000000 --- a/src/main/java/fr/xephi/authme/datasource/ColumnContext.java +++ /dev/null @@ -1,20 +0,0 @@ -package fr.xephi.authme.datasource; - -import fr.xephi.authme.settings.Settings; - -import java.util.HashMap; -import java.util.Map; - -public class ColumnContext { - - private final Settings settings; - private final Map, String> columnNames = new HashMap<>(); - - public ColumnContext(Settings settings) { - this.settings = settings; - } - - public String getName(AuthMeColumns column) { - return columnNames.computeIfAbsent(column, k -> settings.getProperty(k.getNameProperty())); - } -} diff --git a/src/main/java/fr/xephi/authme/datasource/MySQL.java b/src/main/java/fr/xephi/authme/datasource/MySQL.java index f098d4683..8e501ae0c 100644 --- a/src/main/java/fr/xephi/authme/datasource/MySQL.java +++ b/src/main/java/fr/xephi/authme/datasource/MySQL.java @@ -6,6 +6,7 @@ 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.AuthMeColumns; import fr.xephi.authme.datasource.columnshandler.AuthMeColumnsHandler; import fr.xephi.authme.datasource.mysqlextensions.MySqlExtension; import fr.xephi.authme.datasource.mysqlextensions.MySqlExtensionsFactory; @@ -13,7 +14,6 @@ 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; @@ -103,8 +103,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(sql -> getConnection().prepareStatement(sql), 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); @@ -317,33 +316,11 @@ public class MySQL implements DataSource { @Override public boolean saveAuth(PlayerAuth auth) { + columnsHandler.insert(auth, + AuthMeColumns.NAME, AuthMeColumns.NICK_NAME, AuthMeColumns.PASSWORD, AuthMeColumns.SALT, + AuthMeColumns.EMAIL, AuthMeColumns.REGISTRATION_DATE, AuthMeColumns.REGISTRATION_IP); + 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( diff --git a/src/main/java/fr/xephi/authme/datasource/SQLite.java b/src/main/java/fr/xephi/authme/datasource/SQLite.java index 57d12a6b4..0b2361aa8 100644 --- a/src/main/java/fr/xephi/authme/datasource/SQLite.java +++ b/src/main/java/fr/xephi/authme/datasource/SQLite.java @@ -4,11 +4,11 @@ import ch.jalu.datasourcecolumns.data.DataSourceValues; import com.google.common.annotations.VisibleForTesting; import fr.xephi.authme.ConsoleLogger; 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 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; @@ -254,46 +254,9 @@ public class SQLite implements DataSource { @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; + return columnsHandler.insert(auth, + AuthMeColumns.NAME, AuthMeColumns.NICK_NAME, AuthMeColumns.PASSWORD, AuthMeColumns.SALT, + AuthMeColumns.EMAIL, AuthMeColumns.REGISTRATION_DATE, AuthMeColumns.REGISTRATION_IP); } @Override diff --git a/src/main/java/fr/xephi/authme/datasource/AuthMeColumns.java b/src/main/java/fr/xephi/authme/datasource/columnshandler/AuthMeColumns.java similarity index 61% rename from src/main/java/fr/xephi/authme/datasource/AuthMeColumns.java rename to src/main/java/fr/xephi/authme/datasource/columnshandler/AuthMeColumns.java index 657084aea..246bf5581 100644 --- a/src/main/java/fr/xephi/authme/datasource/AuthMeColumns.java +++ b/src/main/java/fr/xephi/authme/datasource/columnshandler/AuthMeColumns.java @@ -1,14 +1,27 @@ -package fr.xephi.authme.datasource; +package fr.xephi.authme.datasource.columnshandler; import ch.jalu.configme.properties.Property; import ch.jalu.datasourcecolumns.ColumnType; import ch.jalu.datasourcecolumns.DependentColumn; -import ch.jalu.datasourcecolumns.StandardTypes; import fr.xephi.authme.data.auth.PlayerAuth; import fr.xephi.authme.settings.properties.DatabaseSettings; import java.util.function.Function; +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; + +/** + * Column definitions for the AuthMe table. + * + * @param the column type + * @see PlayerAuth + */ public final class AuthMeColumns implements DependentColumn { public static final AuthMeColumns NAME = createString( @@ -20,15 +33,24 @@ public final class AuthMeColumns implements DependentColumn PASSWORD = createString( DatabaseSettings.MYSQL_COL_PASSWORD, auth -> auth.getPassword().getHash()); - public static final AuthMeColumns SALT = new AuthMeColumns<>( - StandardTypes.STRING, DatabaseSettings.MYSQL_COL_SALT, auth -> auth.getPassword().getSalt(), true); + public static final AuthMeColumns SALT = createString( + DatabaseSettings.MYSQL_COL_SALT, auth -> auth.getPassword().getSalt(), OPTIONAL); public static final AuthMeColumns EMAIL = createString( - DatabaseSettings.MYSQL_COL_EMAIL, PlayerAuth::getEmail); + DatabaseSettings.MYSQL_COL_EMAIL, PlayerAuth::getEmail, DEFAULT_FOR_NULL); public static final AuthMeColumns LAST_IP = createString( DatabaseSettings.MYSQL_COL_LAST_IP, PlayerAuth::getLastIp); + public static final AuthMeColumns GROUP_ID = createInteger( + DatabaseSettings.MYSQL_COL_GROUP, PlayerAuth::getGroupId, OPTIONAL); + + public static final AuthMeColumns REGISTRATION_IP = createString( + DatabaseSettings.MYSQL_COL_REGISTER_IP, PlayerAuth::getRegistrationIp); + + public static final AuthMeColumns REGISTRATION_DATE = createLong( + DatabaseSettings.MYSQL_COL_REGISTER_DATE, PlayerAuth::getRegistrationDate); + public static final AuthMeColumns LOCATION_X = createDouble( DatabaseSettings.MYSQL_COL_LASTLOC_X, PlayerAuth::getQuitLocX); @@ -52,28 +74,15 @@ public final class AuthMeColumns implements DependentColumn nameProperty; private final Function playerAuthGetter; private final boolean isOptional; + private final boolean useDefaultForNull; - private AuthMeColumns(ColumnType type, Property nameProperty, Function playerAuthGetter, - boolean isOptional) { + AuthMeColumns(ColumnType type, Property nameProperty, Function playerAuthGetter, + boolean isOptional, boolean useDefaultForNull) { this.columnType = type; this.nameProperty = nameProperty; this.playerAuthGetter = playerAuthGetter; this.isOptional = isOptional; - } - - private static AuthMeColumns createString(Property nameProperty, - Function getter) { - return new AuthMeColumns<>(StandardTypes.STRING, nameProperty, getter, false); - } - - private static AuthMeColumns createDouble(Property nameProperty, - Function getter) { - return new AuthMeColumns<>(new DoubleType(), nameProperty, getter, false); - } - - private static AuthMeColumns createFloat(Property nameProperty, - Function getter) { - return new AuthMeColumns<>(new FloatType(), nameProperty, getter, false); + this.useDefaultForNull = useDefaultForNull; } @@ -103,23 +112,6 @@ public final class AuthMeColumns implements DependentColumn { - - @Override - public Class getClazz() { - return Double.class; - } - } - - private static final class FloatType implements ColumnType { - - @Override - public Class getClazz() { - return Float.class; - } + return useDefaultForNull && columnContext.hasDefaultSupport(); } } 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..420a26bc0 --- /dev/null +++ b/src/main/java/fr/xephi/authme/datasource/columnshandler/AuthMeColumnsFactory.java @@ -0,0 +1,76 @@ +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 AuthMeColumns} constants. + */ +final class AuthMeColumnsFactory { + + private AuthMeColumnsFactory() { + } + + static AuthMeColumns createInteger(Property nameProperty, + Function playerAuthGetter, + ColumnOptions... options) { + return createInternal(StandardTypes.INTEGER, nameProperty, playerAuthGetter, options); + } + + static AuthMeColumns createLong(Property nameProperty, + Function playerAuthGetter, + ColumnOptions... options) { + return createInternal(StandardTypes.LONG, nameProperty, playerAuthGetter, options); + } + + static AuthMeColumns createString(Property nameProperty, + Function playerAuthGetter, + ColumnOptions... options) { + return createInternal(StandardTypes.STRING, nameProperty, playerAuthGetter, options); + } + + static AuthMeColumns createDouble(Property nameProperty, + Function playerAuthGetter, + ColumnOptions... options) { + return createInternal(StandardTypes.DOUBLE, nameProperty, playerAuthGetter, options); + } + + static AuthMeColumns createFloat(Property nameProperty, + Function playerAuthGetter, + ColumnOptions... options) { + return createInternal(StandardTypes.FLOAT, nameProperty, playerAuthGetter, options); + } + + private static AuthMeColumns createInternal(ColumnType type, Property nameProperty, + Function authGetter, ColumnOptions... options) { + return new AuthMeColumns<>(type, nameProperty, authGetter, isOptional(options), hasDefaultForNull(options)); + } + + 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 index b4c02dc93..a35c8c97c 100644 --- a/src/main/java/fr/xephi/authme/datasource/columnshandler/AuthMeColumnsHandler.java +++ b/src/main/java/fr/xephi/authme/datasource/columnshandler/AuthMeColumnsHandler.java @@ -4,12 +4,9 @@ import ch.jalu.datasourcecolumns.data.DataSourceValue; import ch.jalu.datasourcecolumns.data.DataSourceValues; import ch.jalu.datasourcecolumns.data.UpdateValues; 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.datasource.AuthMeColumns; -import fr.xephi.authme.datasource.ColumnContext; import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.properties.DatabaseSettings; @@ -38,7 +35,7 @@ public final class AuthMeColumnsHandler { * @return created column handler */ public static AuthMeColumnsHandler createForSqlite(Connection connection, Settings settings) { - ColumnContext columnContext = new ColumnContext(settings); + ColumnContext columnContext = new ColumnContext(settings, false); String tableName = settings.getProperty(DatabaseSettings.MYSQL_TABLE); String nameColumn = settings.getProperty(DatabaseSettings.MYSQL_COL_NAME); @@ -50,19 +47,18 @@ public final class AuthMeColumnsHandler { /** * Creates a column handler for MySQL. * - * @param preparedStatementGenerator supplier of SQL prepared statements with a connection to the database + * @param connectionSupplier supplier of connections from the connection pool * @param settings plugin settings * @return created column handler */ - public static AuthMeColumnsHandler createForMySql(PreparedStatementGenerator preparedStatementGenerator, - Settings settings) { - ColumnContext columnContext = new ColumnContext(settings); + 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<>(preparedStatementGenerator, - columnContext, tableName, nameColumn, new ResultSetValueRetriever<>(columnContext), - new PredicateSqlGenerator<>(columnContext)); + SqlColumnsHandler sqlColHandler = new SqlColumnsHandler<>( + new MySqlPreparedStatementGenerator(connectionSupplier), columnContext, tableName, nameColumn, + new ResultSetValueRetriever<>(columnContext), new PredicateSqlGenerator<>(columnContext)); return new AuthMeColumnsHandler(sqlColHandler); } @@ -138,4 +134,20 @@ public final class AuthMeColumnsHandler { public DataSourceValues retrieve(String name, AuthMeColumns... columns) throws SQLException { return internalHandler.retrieve(name.toLowerCase(), columns); } + + /** + * 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, AuthMeColumns... columns) { + try { + return internalHandler.insert(auth, columns); + } catch (SQLException e) { + logSqlException(e); + return false; + } + } } 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..8759935db --- /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(AuthMeColumns 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..4d419a219 --- /dev/null +++ b/src/main/java/fr/xephi/authme/datasource/columnshandler/ConnectionSupplier.java @@ -0,0 +1,17 @@ +package fr.xephi.authme.datasource.columnshandler; + +import java.sql.Connection; +import java.sql.SQLException; + +/** + * Supplier of connections to a database. + */ +@FunctionalInterface +public interface ConnectionSupplier { + + /** + * @return connection object to the database + */ + Connection get() throws SQLException; + +} 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/test/java/fr/xephi/authme/ClassesConsistencyTest.java b/src/test/java/fr/xephi/authme/ClassesConsistencyTest.java index 4005dc798..c7f093982 100644 --- a/src/test/java/fr/xephi/authme/ClassesConsistencyTest.java +++ b/src/test/java/fr/xephi/authme/ClassesConsistencyTest.java @@ -5,8 +5,8 @@ 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.AuthMeColumns; import fr.xephi.authme.datasource.Columns; +import fr.xephi.authme.datasource.columnshandler.AuthMeColumns; import fr.xephi.authme.datasource.mysqlextensions.MySqlExtension; import fr.xephi.authme.initialization.HasCleanup; import fr.xephi.authme.process.register.executors.RegistrationMethod; From 137fc3d50579cfc9c2db29dd86f19fc4cc202325 Mon Sep 17 00:00:00 2001 From: ljacqu Date: Sat, 24 Mar 2018 22:53:30 +0100 Subject: [PATCH 04/10] #1539 Use columns handler in more datasource methods; fix case-insensitivity for SQLite --- .../fr/xephi/authme/datasource/MySQL.java | 81 +++++-------------- .../fr/xephi/authme/datasource/SQLite.java | 81 ++++--------------- .../columnshandler/AuthMeColumns.java | 3 + .../columnshandler/AuthMeColumnsHandler.java | 35 +++++++- .../datasource/MySqlIntegrationTest.java | 4 +- 5 files changed, 75 insertions(+), 129 deletions(-) diff --git a/src/main/java/fr/xephi/authme/datasource/MySQL.java b/src/main/java/fr/xephi/authme/datasource/MySQL.java index 8e501ae0c..e7739fb18 100644 --- a/src/main/java/fr/xephi/authme/datasource/MySQL.java +++ b/src/main/java/fr/xephi/authme/datasource/MySQL.java @@ -1,6 +1,7 @@ package fr.xephi.authme.datasource; import ch.jalu.datasourcecolumns.data.DataSourceValues; +import ch.jalu.datasourcecolumns.predicate.AlwaysTruePredicate; import com.google.common.annotations.VisibleForTesting; import com.zaxxer.hikari.HikariDataSource; import com.zaxxer.hikari.pool.HikariPool.PoolInitializationException; @@ -23,11 +24,14 @@ import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; 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.getNullableLong; import static fr.xephi.authme.datasource.SqlDataSourceUtils.logSqlException; @@ -269,24 +273,20 @@ 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); + try { + return columnsHandler.retrieve(user, AuthMeColumns.NAME).rowExists(); + } catch (SQLException e) { + logSqlException(e); + return false; } - return false; } @Override public HashedPassword getPassword(String user) { try { - DataSourceValues passwordResult = columnsHandler.retrieve(user, AuthMeColumns.PASSWORD, AuthMeColumns.SALT); - if (passwordResult.rowExists()) { - return new HashedPassword(passwordResult.get(AuthMeColumns.PASSWORD), passwordResult.get(AuthMeColumns.SALT)); + 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); @@ -354,19 +354,7 @@ public class MySQL implements DataSource { @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; + return columnsHandler.update(auth, AuthMeColumns.LAST_IP, AuthMeColumns.LAST_LOGIN, AuthMeColumns.NICK_NAME); } @Override @@ -427,35 +415,17 @@ 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); + try { + return columnsHandler.retrieve(eq(AuthMeColumns.LAST_IP, ip), AuthMeColumns.NAME); + } catch (SQLException e) { + logSqlException(e); + return Collections.emptyList(); } - 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; + return columnsHandler.count(eqIgnoreCase(AuthMeColumns.EMAIL, email)); } @Override @@ -566,18 +536,7 @@ public class MySQL implements DataSource { @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; + return columnsHandler.count(new AlwaysTruePredicate<>()); } @Override diff --git a/src/main/java/fr/xephi/authme/datasource/SQLite.java b/src/main/java/fr/xephi/authme/datasource/SQLite.java index 0b2361aa8..01f13a50e 100644 --- a/src/main/java/fr/xephi/authme/datasource/SQLite.java +++ b/src/main/java/fr/xephi/authme/datasource/SQLite.java @@ -1,6 +1,7 @@ package fr.xephi.authme.datasource; import ch.jalu.datasourcecolumns.data.DataSourceValues; +import ch.jalu.datasourcecolumns.predicate.AlwaysTruePredicate; import com.google.common.annotations.VisibleForTesting; import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.data.auth.PlayerAuth; @@ -20,11 +21,14 @@ import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; 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.getNullableLong; import static fr.xephi.authme.datasource.SqlDataSourceUtils.logSqlException; @@ -211,14 +215,10 @@ 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()); + try { + return columnsHandler.retrieve(user, AuthMeColumns.NAME).rowExists(); + } catch (SQLException e) { + logSqlException(e); return false; } } @@ -273,19 +273,7 @@ public class SQLite implements DataSource { @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; + return columnsHandler.update(auth, AuthMeColumns.LAST_IP, AuthMeColumns.LAST_LOGIN, AuthMeColumns.NICK_NAME); } @Override @@ -360,36 +348,17 @@ 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); + try { + return columnsHandler.retrieve(eq(AuthMeColumns.LAST_IP, ip), AuthMeColumns.NAME); + } catch (SQLException e) { + logSqlException(e); + return Collections.emptyList(); } - 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; + return columnsHandler.count(eqIgnoreCase(AuthMeColumns.EMAIL, email)); } @Override @@ -491,15 +460,7 @@ public class SQLite implements DataSource { @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; + return columnsHandler.count(new AlwaysTruePredicate<>()); } @Override @@ -607,16 +568,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 index 246bf5581..109ea5a63 100644 --- a/src/main/java/fr/xephi/authme/datasource/columnshandler/AuthMeColumns.java +++ b/src/main/java/fr/xephi/authme/datasource/columnshandler/AuthMeColumns.java @@ -45,6 +45,9 @@ public final class AuthMeColumns implements DependentColumn GROUP_ID = createInteger( DatabaseSettings.MYSQL_COL_GROUP, PlayerAuth::getGroupId, OPTIONAL); + public static final AuthMeColumns LAST_LOGIN = createLong( + DatabaseSettings.MYSQL_COL_LASTLOGIN, PlayerAuth::getLastLogin); + public static final AuthMeColumns REGISTRATION_IP = createString( DatabaseSettings.MYSQL_COL_REGISTER_IP, PlayerAuth::getRegistrationIp); diff --git a/src/main/java/fr/xephi/authme/datasource/columnshandler/AuthMeColumnsHandler.java b/src/main/java/fr/xephi/authme/datasource/columnshandler/AuthMeColumnsHandler.java index a35c8c97c..08202e396 100644 --- a/src/main/java/fr/xephi/authme/datasource/columnshandler/AuthMeColumnsHandler.java +++ b/src/main/java/fr/xephi/authme/datasource/columnshandler/AuthMeColumnsHandler.java @@ -3,7 +3,9 @@ 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; @@ -12,6 +14,7 @@ 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; @@ -39,8 +42,9 @@ public final class AuthMeColumnsHandler { String tableName = settings.getProperty(DatabaseSettings.MYSQL_TABLE); String nameColumn = settings.getProperty(DatabaseSettings.MYSQL_COL_NAME); - SqlColumnsHandler sqlColHandler = - new SqlColumnsHandler<>(connection, columnContext, tableName, nameColumn); + SqlColumnsHandler sqlColHandler = new SqlColumnsHandler<>( + PreparedStatementGenerator.fromConnection(connection), columnContext, tableName, nameColumn, + new ResultSetValueRetriever<>(columnContext), new PredicateSqlGenerator<>(columnContext, true)); return new AuthMeColumnsHandler(sqlColHandler); } @@ -135,6 +139,18 @@ public final class AuthMeColumnsHandler { 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 + */ + public List retrieve(Predicate predicate, AuthMeColumns column) throws SQLException { + return internalHandler.retrieve(predicate, column); + } + /** * Inserts the given values into a new row, as taken from the player auth. * @@ -150,4 +166,19 @@ public final class AuthMeColumnsHandler { 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/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); From 4595a141914817b6764d8fa16847af9d4eaae5cd Mon Sep 17 00:00:00 2001 From: ljacqu Date: Sun, 25 Mar 2018 11:52:40 +0200 Subject: [PATCH 05/10] #1539 Add support for columns that are not on player auth (is_logged, has_session) --- .../executable/authme/GetEmailCommand.java | 6 +- .../authme/debug/TestEmailSender.java | 6 +- .../executable/email/RecoverEmailCommand.java | 6 +- .../authme/data/VerificationCodeManager.java | 10 +- .../authme/datasource/CacheDataSource.java | 8 +- .../xephi/authme/datasource/DataSource.java | 3 +- .../authme/datasource/DataSourceResult.java | 53 ---------- .../fr/xephi/authme/datasource/FlatFile.java | 3 +- .../fr/xephi/authme/datasource/MySQL.java | 95 +++++------------- .../fr/xephi/authme/datasource/SQLite.java | 64 ++++--------- .../columnshandler/AuthMeColumns.java | 96 ++++++------------- .../columnshandler/AuthMeColumnsFactory.java | 45 +++++---- .../columnshandler/AuthMeColumnsHandler.java | 30 ++++-- .../columnshandler/ColumnContext.java | 4 +- .../columnshandler/DataSourceColumn.java | 57 +++++++++++ .../columnshandler/PlayerAuthColumn.java | 32 +++++++ .../xephi/authme/ClassesConsistencyTest.java | 5 +- .../authme/GetEmailCommandTest.java | 6 +- .../email/RecoverEmailCommandTest.java | 12 +-- .../data/VerificationCodeManagerTest.java | 10 +- .../AbstractDataSourceIntegrationTest.java | 8 +- 21 files changed, 257 insertions(+), 302 deletions(-) delete mode 100644 src/main/java/fr/xephi/authme/datasource/DataSourceResult.java create mode 100644 src/main/java/fr/xephi/authme/datasource/columnshandler/DataSourceColumn.java create mode 100644 src/main/java/fr/xephi/authme/datasource/columnshandler/PlayerAuthColumn.java 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/CacheDataSource.java b/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java index 39f04a53c..5081cf09c 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 6f97951db..a0a47adea 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 d234da556..56db1e6e7 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 e7739fb18..b8e487e2b 100644 --- a/src/main/java/fr/xephi/authme/datasource/MySQL.java +++ b/src/main/java/fr/xephi/authme/datasource/MySQL.java @@ -1,5 +1,7 @@ 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 com.google.common.annotations.VisibleForTesting; @@ -448,90 +450,49 @@ public class MySQL implements DataSource { @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); + 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; } - 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); - } + columnsHandler.update(user, AuthMeColumns.IS_LOGGED, 1); } @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); - } + columnsHandler.update(user, AuthMeColumns.IS_LOGGED, 0); } @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); + 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; } - 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); - } + columnsHandler.update(user, AuthMeColumns.HAS_SESSION, 1); } @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); - } + columnsHandler.update(user, AuthMeColumns.HAS_SESSION, 0); } @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); - } + columnsHandler.update(eq(AuthMeColumns.IS_LOGGED, 1), AuthMeColumns.IS_LOGGED, 0); } @Override @@ -545,19 +506,13 @@ public class MySQL implements DataSource { } @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); + public DataSourceValue getEmail(String user) { + try { + return columnsHandler.retrieve(user, AuthMeColumns.EMAIL); + } catch (SQLException e) { + logSqlException(e); + return DataSourceValueImpl.unknownRow(); } - return DataSourceResult.unknownPlayer(); } @Override diff --git a/src/main/java/fr/xephi/authme/datasource/SQLite.java b/src/main/java/fr/xephi/authme/datasource/SQLite.java index 01f13a50e..5c78e0bbe 100644 --- a/src/main/java/fr/xephi/authme/datasource/SQLite.java +++ b/src/main/java/fr/xephi/authme/datasource/SQLite.java @@ -1,5 +1,7 @@ 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 com.google.common.annotations.VisibleForTesting; @@ -408,54 +410,28 @@ public class SQLite implements DataSource { @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); + 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; } - 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); - } + columnsHandler.update(user, AuthMeColumns.HAS_SESSION, 1); } @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); - } + columnsHandler.update(user, AuthMeColumns.HAS_SESSION, 0); } @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); - } + columnsHandler.update(eq(AuthMeColumns.IS_LOGGED, 1), AuthMeColumns.IS_LOGGED, 0); } @Override @@ -469,19 +445,13 @@ public class SQLite implements DataSource { } @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); + public DataSourceValue getEmail(String user) { + try { + return columnsHandler.retrieve(user, AuthMeColumns.EMAIL); + } catch (SQLException e) { + logSqlException(e); + return DataSourceValueImpl.unknownRow(); } - return DataSourceResult.unknownPlayer(); } @Override diff --git a/src/main/java/fr/xephi/authme/datasource/columnshandler/AuthMeColumns.java b/src/main/java/fr/xephi/authme/datasource/columnshandler/AuthMeColumns.java index 109ea5a63..5c235095f 100644 --- a/src/main/java/fr/xephi/authme/datasource/columnshandler/AuthMeColumns.java +++ b/src/main/java/fr/xephi/authme/datasource/columnshandler/AuthMeColumns.java @@ -1,13 +1,8 @@ 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 fr.xephi.authme.settings.properties.DatabaseSettings; -import java.util.function.Function; - 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; @@ -17,104 +12,71 @@ import static fr.xephi.authme.datasource.columnshandler.AuthMeColumnsFactory.cre import static fr.xephi.authme.datasource.columnshandler.AuthMeColumnsFactory.createString; /** - * Column definitions for the AuthMe table. - * - * @param the column type - * @see PlayerAuth + * Contains column definitions for the AuthMe table. */ -public final class AuthMeColumns implements DependentColumn { +public final class AuthMeColumns { - public static final AuthMeColumns NAME = createString( + public static final PlayerAuthColumn NAME = createString( DatabaseSettings.MYSQL_COL_NAME, PlayerAuth::getNickname); - public static final AuthMeColumns NICK_NAME = createString( + public static final PlayerAuthColumn NICK_NAME = createString( DatabaseSettings.MYSQL_COL_REALNAME, PlayerAuth::getRealName); - public static final AuthMeColumns PASSWORD = createString( + public static final PlayerAuthColumn PASSWORD = createString( DatabaseSettings.MYSQL_COL_PASSWORD, auth -> auth.getPassword().getHash()); - public static final AuthMeColumns SALT = createString( + public static final PlayerAuthColumn SALT = createString( DatabaseSettings.MYSQL_COL_SALT, auth -> auth.getPassword().getSalt(), OPTIONAL); - public static final AuthMeColumns EMAIL = createString( + public static final PlayerAuthColumn EMAIL = createString( DatabaseSettings.MYSQL_COL_EMAIL, PlayerAuth::getEmail, DEFAULT_FOR_NULL); - public static final AuthMeColumns LAST_IP = createString( + public static final PlayerAuthColumn LAST_IP = createString( DatabaseSettings.MYSQL_COL_LAST_IP, PlayerAuth::getLastIp); - public static final AuthMeColumns GROUP_ID = createInteger( + public static final PlayerAuthColumn GROUP_ID = createInteger( DatabaseSettings.MYSQL_COL_GROUP, PlayerAuth::getGroupId, OPTIONAL); - public static final AuthMeColumns LAST_LOGIN = createLong( + public static final PlayerAuthColumn LAST_LOGIN = createLong( DatabaseSettings.MYSQL_COL_LASTLOGIN, PlayerAuth::getLastLogin); - public static final AuthMeColumns REGISTRATION_IP = createString( + public static final PlayerAuthColumn REGISTRATION_IP = createString( DatabaseSettings.MYSQL_COL_REGISTER_IP, PlayerAuth::getRegistrationIp); - public static final AuthMeColumns REGISTRATION_DATE = createLong( + public static final PlayerAuthColumn REGISTRATION_DATE = createLong( DatabaseSettings.MYSQL_COL_REGISTER_DATE, PlayerAuth::getRegistrationDate); - public static final AuthMeColumns LOCATION_X = createDouble( + // -------- + // Location columns + // -------- + public static final PlayerAuthColumn LOCATION_X = createDouble( DatabaseSettings.MYSQL_COL_LASTLOC_X, PlayerAuth::getQuitLocX); - public static final AuthMeColumns LOCATION_Y = createDouble( + public static final PlayerAuthColumn LOCATION_Y = createDouble( DatabaseSettings.MYSQL_COL_LASTLOC_Y, PlayerAuth::getQuitLocY); - public static final AuthMeColumns LOCATION_Z = createDouble( + public static final PlayerAuthColumn LOCATION_Z = createDouble( DatabaseSettings.MYSQL_COL_LASTLOC_Z, PlayerAuth::getQuitLocZ); - public static final AuthMeColumns LOCATION_WORLD = createString( + public static final PlayerAuthColumn LOCATION_WORLD = createString( DatabaseSettings.MYSQL_COL_LASTLOC_WORLD, PlayerAuth::getWorld); - public static final AuthMeColumns LOCATION_YAW = createFloat( + public static final PlayerAuthColumn LOCATION_YAW = createFloat( DatabaseSettings.MYSQL_COL_LASTLOC_YAW, PlayerAuth::getYaw); - public static final AuthMeColumns LOCATION_PITCH = createFloat( + 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); - private final ColumnType columnType; - private final Property nameProperty; - private final Function playerAuthGetter; - private final boolean isOptional; - private final boolean useDefaultForNull; - - AuthMeColumns(ColumnType type, Property nameProperty, Function playerAuthGetter, - boolean isOptional, boolean useDefaultForNull) { - this.columnType = type; - this.nameProperty = nameProperty; - this.playerAuthGetter = playerAuthGetter; - this.isOptional = isOptional; - this.useDefaultForNull = useDefaultForNull; - } + public static final DataSourceColumn HAS_SESSION = createInteger( + DatabaseSettings.MYSQL_COL_HASSESSION); - public Property getNameProperty() { - return nameProperty; - } - - @Override - public T getValueFromDependent(PlayerAuth playerAuth) { - return playerAuthGetter.apply(playerAuth); - } - - @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(); + 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 index 420a26bc0..3400f76cd 100644 --- a/src/main/java/fr/xephi/authme/datasource/columnshandler/AuthMeColumnsFactory.java +++ b/src/main/java/fr/xephi/authme/datasource/columnshandler/AuthMeColumnsFactory.java @@ -8,46 +8,53 @@ import fr.xephi.authme.data.auth.PlayerAuth; import java.util.function.Function; /** - * Util class for initializing {@link AuthMeColumns} constants. + * Util class for initializing {@link DataSourceColumn} objects. */ final class AuthMeColumnsFactory { private AuthMeColumnsFactory() { } - static AuthMeColumns createInteger(Property nameProperty, - Function playerAuthGetter, - ColumnOptions... options) { + 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 AuthMeColumns createLong(Property nameProperty, - Function playerAuthGetter, - ColumnOptions... options) { + static PlayerAuthColumn createLong(Property nameProperty, + Function playerAuthGetter, + ColumnOptions... options) { return createInternal(StandardTypes.LONG, nameProperty, playerAuthGetter, options); } - static AuthMeColumns createString(Property nameProperty, - Function playerAuthGetter, - ColumnOptions... options) { + static PlayerAuthColumn createString(Property nameProperty, + Function playerAuthGetter, + ColumnOptions... options) { return createInternal(StandardTypes.STRING, nameProperty, playerAuthGetter, options); } - static AuthMeColumns createDouble(Property nameProperty, - Function playerAuthGetter, - ColumnOptions... options) { + static PlayerAuthColumn createDouble(Property nameProperty, + Function playerAuthGetter, + ColumnOptions... options) { return createInternal(StandardTypes.DOUBLE, nameProperty, playerAuthGetter, options); } - static AuthMeColumns createFloat(Property nameProperty, - Function playerAuthGetter, - ColumnOptions... options) { + static PlayerAuthColumn createFloat(Property nameProperty, + Function playerAuthGetter, + ColumnOptions... options) { return createInternal(StandardTypes.FLOAT, nameProperty, playerAuthGetter, options); } - private static AuthMeColumns createInternal(ColumnType type, Property nameProperty, - Function authGetter, ColumnOptions... options) { - return new AuthMeColumns<>(type, nameProperty, authGetter, isOptional(options), hasDefaultForNull(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) { diff --git a/src/main/java/fr/xephi/authme/datasource/columnshandler/AuthMeColumnsHandler.java b/src/main/java/fr/xephi/authme/datasource/columnshandler/AuthMeColumnsHandler.java index 08202e396..7b6657126 100644 --- a/src/main/java/fr/xephi/authme/datasource/columnshandler/AuthMeColumnsHandler.java +++ b/src/main/java/fr/xephi/authme/datasource/columnshandler/AuthMeColumnsHandler.java @@ -75,7 +75,7 @@ public final class AuthMeColumnsHandler { * @param the column type * @return true upon success, false otherwise */ - public boolean update(String name, AuthMeColumns column, T value) { + public boolean update(String name, DataSourceColumn column, T value) { try { return internalHandler.update(name, column, value); } catch (SQLException e) { @@ -91,7 +91,7 @@ public final class AuthMeColumnsHandler { * @param columns the columns to update in the row * @return true upon success, false otherwise */ - public boolean update(PlayerAuth auth, AuthMeColumns... columns) { + public boolean update(PlayerAuth auth, PlayerAuthColumn... columns) { try { return internalHandler.update(auth.getNickname(), auth, columns); } catch (SQLException e) { @@ -116,6 +116,24 @@ public final class AuthMeColumnsHandler { } } + /** + * 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. * @@ -124,7 +142,7 @@ public final class AuthMeColumnsHandler { * @param the column type * @return the result of the lookup */ - public DataSourceValue retrieve(String name, AuthMeColumns column) throws SQLException { + public DataSourceValue retrieve(String name, DataSourceColumn column) throws SQLException { return internalHandler.retrieve(name.toLowerCase(), column); } @@ -135,7 +153,7 @@ public final class AuthMeColumnsHandler { * @param columns the columns to retrieve * @return map-like object with the requested values */ - public DataSourceValues retrieve(String name, AuthMeColumns... columns) throws SQLException { + public DataSourceValues retrieve(String name, DataSourceColumn... columns) throws SQLException { return internalHandler.retrieve(name.toLowerCase(), columns); } @@ -147,7 +165,7 @@ public final class AuthMeColumnsHandler { * @param the column's value type * @return the values of the matching rows */ - public List retrieve(Predicate predicate, AuthMeColumns column) throws SQLException { + public List retrieve(Predicate predicate, DataSourceColumn column) throws SQLException { return internalHandler.retrieve(predicate, column); } @@ -158,7 +176,7 @@ public final class AuthMeColumnsHandler { * @param columns the columns to insert * @return true upon success, false otherwise */ - public boolean insert(PlayerAuth auth, AuthMeColumns... columns) { + public boolean insert(PlayerAuth auth, PlayerAuthColumn... columns) { try { return internalHandler.insert(auth, columns); } catch (SQLException e) { diff --git a/src/main/java/fr/xephi/authme/datasource/columnshandler/ColumnContext.java b/src/main/java/fr/xephi/authme/datasource/columnshandler/ColumnContext.java index 8759935db..554266a05 100644 --- a/src/main/java/fr/xephi/authme/datasource/columnshandler/ColumnContext.java +++ b/src/main/java/fr/xephi/authme/datasource/columnshandler/ColumnContext.java @@ -11,7 +11,7 @@ import java.util.Map; public class ColumnContext { private final Settings settings; - private final Map, String> columnNames = new HashMap<>(); + private final Map, String> columnNames = new HashMap<>(); private final boolean hasDefaultSupport; /** @@ -25,7 +25,7 @@ public class ColumnContext { this.hasDefaultSupport = hasDefaultSupport; } - public String getName(AuthMeColumns column) { + public String getName(DataSourceColumn column) { return columnNames.computeIfAbsent(column, k -> settings.getProperty(k.getNameProperty())); } 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/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/test/java/fr/xephi/authme/ClassesConsistencyTest.java b/src/test/java/fr/xephi/authme/ClassesConsistencyTest.java index c7f093982..eb00d14e0 100644 --- a/src/test/java/fr/xephi/authme/ClassesConsistencyTest.java +++ b/src/test/java/fr/xephi/authme/ClassesConsistencyTest.java @@ -6,7 +6,8 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import fr.xephi.authme.data.captcha.CaptchaCodeStorage; import fr.xephi.authme.datasource.Columns; -import fr.xephi.authme.datasource.columnshandler.AuthMeColumns; +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; @@ -53,7 +54,7 @@ public class ClassesConsistencyTest { int.class, long.class, float.class, String.class, File.class, Enum.class, collectionsUnmodifiableList(), Charset.class, /* AuthMe */ - Property.class, RegistrationMethod.class, AuthMeColumns.class, + Property.class, RegistrationMethod.class, DataSourceColumn.class, PlayerAuthColumn.class, /* Guava */ ImmutableMap.class, ImmutableList.class); 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 70df2d48b..8efee23b4 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; @@ -420,12 +422,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 From 26472b6be32e924813f61841b90087ae46a2ea66 Mon Sep 17 00:00:00 2001 From: ljacqu Date: Sun, 25 Mar 2018 22:27:44 +0200 Subject: [PATCH 06/10] #1539 Create common parent for SQLite and MySQL --- .../datasource/AbstractSqlDataSource.java | 169 +++++++++++++++++ .../fr/xephi/authme/datasource/MySQL.java | 151 +-------------- .../fr/xephi/authme/datasource/SQLite.java | 174 +----------------- .../xephi/authme/ClassesConsistencyTest.java | 2 + 4 files changed, 175 insertions(+), 321 deletions(-) create mode 100644 src/main/java/fr/xephi/authme/datasource/AbstractSqlDataSource.java 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/MySQL.java b/src/main/java/fr/xephi/authme/datasource/MySQL.java index b8e487e2b..9f4456159 100644 --- a/src/main/java/fr/xephi/authme/datasource/MySQL.java +++ b/src/main/java/fr/xephi/authme/datasource/MySQL.java @@ -1,19 +1,13 @@ 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 com.google.common.annotations.VisibleForTesting; 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.AuthMeColumns; 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; @@ -26,14 +20,10 @@ import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; -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.getNullableLong; import static fr.xephi.authme.datasource.SqlDataSourceUtils.logSqlException; @@ -41,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; @@ -54,7 +44,6 @@ public class MySQL implements DataSource { private int maxLifetime; private List columnOthers; private Columns col; - private AuthMeColumnsHandler columnsHandler; private MySqlExtension sqlExtension; private HikariDataSource ds; @@ -273,29 +262,6 @@ public class MySQL implements DataSource { } } - @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 PlayerAuth getAuth(String user) { String sql = "SELECT * FROM " + tableName + " WHERE " + col.NAME + "=?;"; @@ -318,9 +284,7 @@ public class MySQL implements DataSource { @Override public boolean saveAuth(PlayerAuth auth) { - columnsHandler.insert(auth, - AuthMeColumns.NAME, AuthMeColumns.NICK_NAME, AuthMeColumns.PASSWORD, AuthMeColumns.SALT, - AuthMeColumns.EMAIL, AuthMeColumns.REGISTRATION_DATE, AuthMeColumns.REGISTRATION_IP); + super.saveAuth(auth); try (Connection con = getConnection()) { if (!columnOthers.isEmpty()) { @@ -342,23 +306,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) { - return columnsHandler.update(user, - with(AuthMeColumns.PASSWORD, password.getHash()) - .and(AuthMeColumns.SALT, password.getSalt()).build()); - } - - @Override - public boolean updateSession(PlayerAuth auth) { - return columnsHandler.update(auth, AuthMeColumns.LAST_IP, AuthMeColumns.LAST_LOGIN, AuthMeColumns.NICK_NAME); - } - @Override public Set getRecordsToPurge(long until) { Set list = new HashSet<>(); @@ -396,18 +343,6 @@ public class MySQL implements DataSource { return false; } - @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 boolean updateEmail(PlayerAuth auth) { - return columnsHandler.update(auth, AuthMeColumns.EMAIL); - } - @Override public void closeConnection() { if (ds != null && !ds.isClosed()) { @@ -415,21 +350,6 @@ public class MySQL implements DataSource { } } - @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 void purgeRecords(Collection toPurge) { String sql = "DELETE FROM " + tableName + " WHERE " + col.NAME + "=?;"; @@ -448,73 +368,6 @@ public class MySQL implements DataSource { return DataSourceType.MYSQL; } - @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 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 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(); - } - } - @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 5c78e0bbe..b2f639a37 100644 --- a/src/main/java/fr/xephi/authme/datasource/SQLite.java +++ b/src/main/java/fr/xephi/authme/datasource/SQLite.java @@ -1,15 +1,9 @@ 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 com.google.common.annotations.VisibleForTesting; import fr.xephi.authme.ConsoleLogger; 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 fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.properties.DatabaseSettings; @@ -23,14 +17,10 @@ import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; -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.getNullableLong; import static fr.xephi.authme.datasource.SqlDataSourceUtils.logSqlException; @@ -38,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; @@ -46,7 +36,6 @@ public class SQLite implements DataSource { private final String tableName; private final Columns col; private Connection con; - private AuthMeColumnsHandler columnsHandler; /** * Constructor for SQLite. @@ -71,6 +60,7 @@ public class SQLite implements DataSource { ConsoleLogger.logException("Error during SQLite initialization:", ex); throw ex; } + this.columnsHandler = AuthMeColumnsHandler.createForSqlite(con, settings); } @VisibleForTesting @@ -215,29 +205,6 @@ public class SQLite implements DataSource { } } - @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 PlayerAuth getAuth(String user) { String sql = "SELECT * FROM " + tableName + " WHERE LOWER(" + col.NAME + ")=LOWER(?);"; @@ -254,30 +221,6 @@ public class SQLite implements DataSource { 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 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 updateSession(PlayerAuth auth) { - return columnsHandler.update(auth, AuthMeColumns.LAST_IP, AuthMeColumns.LAST_LOGIN, AuthMeColumns.NICK_NAME); - } - @Override public Set getRecordsToPurge(long until) { Set list = new HashSet<>(); @@ -325,18 +268,6 @@ public class SQLite implements DataSource { return false; } - @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 boolean updateEmail(PlayerAuth auth) { - return columnsHandler.update(auth, AuthMeColumns.EMAIL); - } - @Override public void closeConnection() { try { @@ -348,112 +279,11 @@ public class SQLite implements DataSource { } } - @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 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) { - 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 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(); - } - } - @Override public List getAllAuths() { List auths = new ArrayList<>(); diff --git a/src/test/java/fr/xephi/authme/ClassesConsistencyTest.java b/src/test/java/fr/xephi/authme/ClassesConsistencyTest.java index eb00d14e0..f02b5dc9b 100644 --- a/src/test/java/fr/xephi/authme/ClassesConsistencyTest.java +++ b/src/test/java/fr/xephi/authme/ClassesConsistencyTest.java @@ -5,6 +5,7 @@ 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; @@ -62,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 ); From f752b9d7a71b6bc0ee572f59ff54f8165abc5f15 Mon Sep 17 00:00:00 2001 From: Gabriele C Date: Mon, 26 Mar 2018 21:50:56 +0200 Subject: [PATCH 07/10] [CI-SKIP] Fix jenkins url in pom --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b6b1d4ec2..a5c49a3c4 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/ From 68329a876172b53dabcff704be36692f601dadb9 Mon Sep 17 00:00:00 2001 From: RikoDEV Date: Fri, 30 Mar 2018 16:01:22 +0200 Subject: [PATCH 08/10] Update messages_pl.yml (#1548) --- src/main/resources/messages/messages_pl.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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: From fc54c0311b4f8245c4ef1bcf1de5a60576c6504d Mon Sep 17 00:00:00 2001 From: ljacqu Date: Mon, 2 Apr 2018 23:19:13 +0200 Subject: [PATCH 09/10] #1539 Columns handler: finishing touches - Add relocation rule for shading of the library - Fix SQLite connection not being refreshed on reload --- pom.xml | 5 ++++- src/main/java/fr/xephi/authme/datasource/SQLite.java | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 01034dc66..a76536998 100644 --- a/pom.xml +++ b/pom.xml @@ -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 @@ -792,7 +796,6 @@ ch.jalu datasourcecolumns 0.1-SNAPSHOT - compile true diff --git a/src/main/java/fr/xephi/authme/datasource/SQLite.java b/src/main/java/fr/xephi/authme/datasource/SQLite.java index b2f639a37..b7ed2083f 100644 --- a/src/main/java/fr/xephi/authme/datasource/SQLite.java +++ b/src/main/java/fr/xephi/authme/datasource/SQLite.java @@ -60,7 +60,6 @@ public class SQLite extends AbstractSqlDataSource { ConsoleLogger.logException("Error during SQLite initialization:", ex); throw ex; } - this.columnsHandler = AuthMeColumnsHandler.createForSqlite(con, settings); } @VisibleForTesting @@ -86,6 +85,7 @@ public class SQLite extends AbstractSqlDataSource { ConsoleLogger.debug("SQLite driver loaded"); this.con = DriverManager.getConnection("jdbc:sqlite:plugins/AuthMe/" + database + ".db"); + this.columnsHandler = AuthMeColumnsHandler.createForSqlite(con, settings); } /** From 106dea161151a686c014a33ebd0c91e37c92dd35 Mon Sep 17 00:00:00 2001 From: ljacqu Date: Mon, 2 Apr 2018 23:43:52 +0200 Subject: [PATCH 10/10] Minor: fix JavaDoc warnings --- .../datasource/columnshandler/AuthMeColumnsHandler.java | 3 +++ .../authme/datasource/columnshandler/ConnectionSupplier.java | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/fr/xephi/authme/datasource/columnshandler/AuthMeColumnsHandler.java b/src/main/java/fr/xephi/authme/datasource/columnshandler/AuthMeColumnsHandler.java index 7b6657126..bb0d80b77 100644 --- a/src/main/java/fr/xephi/authme/datasource/columnshandler/AuthMeColumnsHandler.java +++ b/src/main/java/fr/xephi/authme/datasource/columnshandler/AuthMeColumnsHandler.java @@ -141,6 +141,7 @@ public final class AuthMeColumnsHandler { * @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); @@ -152,6 +153,7 @@ public final class AuthMeColumnsHandler { * @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); @@ -164,6 +166,7 @@ public final class AuthMeColumnsHandler { * @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); diff --git a/src/main/java/fr/xephi/authme/datasource/columnshandler/ConnectionSupplier.java b/src/main/java/fr/xephi/authme/datasource/columnshandler/ConnectionSupplier.java index 4d419a219..77fbe8f3a 100644 --- a/src/main/java/fr/xephi/authme/datasource/columnshandler/ConnectionSupplier.java +++ b/src/main/java/fr/xephi/authme/datasource/columnshandler/ConnectionSupplier.java @@ -10,7 +10,10 @@ import java.sql.SQLException; public interface ConnectionSupplier { /** - * @return connection object to the database + * Returns a connection to the database. + * + * @return the connection + * @throws SQLException . */ Connection get() throws SQLException;