#1539 Integrate data source columns library
- Create wrapper around SqlColumnsHandler for AuthMe-specific behavior - Integrate columns handler into first SQLite and MySQL method implementations
This commit is contained in:
parent
6251a69d3e
commit
5a58f2c44f
8
pom.xml
8
pom.xml
@ -788,6 +788,14 @@
|
|||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>ch.jalu</groupId>
|
||||||
|
<artifactId>datasourcecolumns</artifactId>
|
||||||
|
<version>0.1-SNAPSHOT</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- Unit Testing Libraries -->
|
<!-- Unit Testing Libraries -->
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|||||||
125
src/main/java/fr/xephi/authme/datasource/AuthMeColumns.java
Normal file
125
src/main/java/fr/xephi/authme/datasource/AuthMeColumns.java
Normal file
@ -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<T> implements DependentColumn<T, ColumnContext, PlayerAuth> {
|
||||||
|
|
||||||
|
public static final AuthMeColumns<String> NAME = createString(
|
||||||
|
DatabaseSettings.MYSQL_COL_NAME, PlayerAuth::getNickname);
|
||||||
|
|
||||||
|
public static final AuthMeColumns<String> NICK_NAME = createString(
|
||||||
|
DatabaseSettings.MYSQL_COL_REALNAME, PlayerAuth::getRealName);
|
||||||
|
|
||||||
|
public static final AuthMeColumns<String> PASSWORD = createString(
|
||||||
|
DatabaseSettings.MYSQL_COL_PASSWORD, auth -> auth.getPassword().getHash());
|
||||||
|
|
||||||
|
public static final AuthMeColumns<String> SALT = new AuthMeColumns<>(
|
||||||
|
StandardTypes.STRING, DatabaseSettings.MYSQL_COL_SALT, auth -> auth.getPassword().getSalt(), true);
|
||||||
|
|
||||||
|
public static final AuthMeColumns<String> EMAIL = createString(
|
||||||
|
DatabaseSettings.MYSQL_COL_EMAIL, PlayerAuth::getEmail);
|
||||||
|
|
||||||
|
public static final AuthMeColumns<String> LAST_IP = createString(
|
||||||
|
DatabaseSettings.MYSQL_COL_LAST_IP, PlayerAuth::getLastIp);
|
||||||
|
|
||||||
|
public static final AuthMeColumns<Double> LOCATION_X = createDouble(
|
||||||
|
DatabaseSettings.MYSQL_COL_LASTLOC_X, PlayerAuth::getQuitLocX);
|
||||||
|
|
||||||
|
public static final AuthMeColumns<Double> LOCATION_Y = createDouble(
|
||||||
|
DatabaseSettings.MYSQL_COL_LASTLOC_Y, PlayerAuth::getQuitLocY);
|
||||||
|
|
||||||
|
public static final AuthMeColumns<Double> LOCATION_Z = createDouble(
|
||||||
|
DatabaseSettings.MYSQL_COL_LASTLOC_Z, PlayerAuth::getQuitLocZ);
|
||||||
|
|
||||||
|
public static final AuthMeColumns<String> LOCATION_WORLD = createString(
|
||||||
|
DatabaseSettings.MYSQL_COL_LASTLOC_WORLD, PlayerAuth::getWorld);
|
||||||
|
|
||||||
|
public static final AuthMeColumns<Float> LOCATION_YAW = createFloat(
|
||||||
|
DatabaseSettings.MYSQL_COL_LASTLOC_YAW, PlayerAuth::getYaw);
|
||||||
|
|
||||||
|
public static final AuthMeColumns<Float> LOCATION_PITCH = createFloat(
|
||||||
|
DatabaseSettings.MYSQL_COL_LASTLOC_PITCH, PlayerAuth::getPitch);
|
||||||
|
|
||||||
|
|
||||||
|
private final ColumnType<T> columnType;
|
||||||
|
private final Property<String> nameProperty;
|
||||||
|
private final Function<PlayerAuth, T> playerAuthGetter;
|
||||||
|
private final boolean isOptional;
|
||||||
|
|
||||||
|
private AuthMeColumns(ColumnType<T> type, Property<String> nameProperty, Function<PlayerAuth, T> playerAuthGetter,
|
||||||
|
boolean isOptional) {
|
||||||
|
this.columnType = type;
|
||||||
|
this.nameProperty = nameProperty;
|
||||||
|
this.playerAuthGetter = playerAuthGetter;
|
||||||
|
this.isOptional = isOptional;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static AuthMeColumns<String> createString(Property<String> nameProperty,
|
||||||
|
Function<PlayerAuth, String> getter) {
|
||||||
|
return new AuthMeColumns<>(StandardTypes.STRING, nameProperty, getter, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static AuthMeColumns<Double> createDouble(Property<String> nameProperty,
|
||||||
|
Function<PlayerAuth, Double> getter) {
|
||||||
|
return new AuthMeColumns<>(new DoubleType(), nameProperty, getter, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static AuthMeColumns<Float> createFloat(Property<String> nameProperty,
|
||||||
|
Function<PlayerAuth, Float> getter) {
|
||||||
|
return new AuthMeColumns<>(new FloatType(), nameProperty, getter, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Property<String> 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<T> 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<Double> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<Double> getClazz() {
|
||||||
|
return Double.class;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class FloatType implements ColumnType<Float> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<Float> getClazz() {
|
||||||
|
return Float.class;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
20
src/main/java/fr/xephi/authme/datasource/ColumnContext.java
Normal file
20
src/main/java/fr/xephi/authme/datasource/ColumnContext.java
Normal file
@ -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<AuthMeColumns<?>, 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()));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,10 +1,12 @@
|
|||||||
package fr.xephi.authme.datasource;
|
package fr.xephi.authme.datasource;
|
||||||
|
|
||||||
|
import ch.jalu.datasourcecolumns.data.DataSourceValues;
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.zaxxer.hikari.HikariDataSource;
|
import com.zaxxer.hikari.HikariDataSource;
|
||||||
import com.zaxxer.hikari.pool.HikariPool.PoolInitializationException;
|
import com.zaxxer.hikari.pool.HikariPool.PoolInitializationException;
|
||||||
import fr.xephi.authme.ConsoleLogger;
|
import fr.xephi.authme.ConsoleLogger;
|
||||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
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.MySqlExtension;
|
||||||
import fr.xephi.authme.datasource.mysqlextensions.MySqlExtensionsFactory;
|
import fr.xephi.authme.datasource.mysqlextensions.MySqlExtensionsFactory;
|
||||||
import fr.xephi.authme.security.crypts.HashedPassword;
|
import fr.xephi.authme.security.crypts.HashedPassword;
|
||||||
@ -25,6 +27,7 @@ import java.util.HashSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
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.getNullableLong;
|
||||||
import static fr.xephi.authme.datasource.SqlDataSourceUtils.logSqlException;
|
import static fr.xephi.authme.datasource.SqlDataSourceUtils.logSqlException;
|
||||||
|
|
||||||
@ -45,6 +48,7 @@ public class MySQL implements DataSource {
|
|||||||
private int maxLifetime;
|
private int maxLifetime;
|
||||||
private List<String> columnOthers;
|
private List<String> columnOthers;
|
||||||
private Columns col;
|
private Columns col;
|
||||||
|
private AuthMeColumnsHandler columnsHandler;
|
||||||
private MySqlExtension sqlExtension;
|
private MySqlExtension sqlExtension;
|
||||||
private HikariDataSource ds;
|
private HikariDataSource ds;
|
||||||
|
|
||||||
@ -99,6 +103,8 @@ public class MySQL implements DataSource {
|
|||||||
this.tableName = settings.getProperty(DatabaseSettings.MYSQL_TABLE);
|
this.tableName = settings.getProperty(DatabaseSettings.MYSQL_TABLE);
|
||||||
this.columnOthers = settings.getProperty(HooksSettings.MYSQL_OTHER_USERNAME_COLS);
|
this.columnOthers = settings.getProperty(HooksSettings.MYSQL_OTHER_USERNAME_COLS);
|
||||||
this.col = new Columns(settings);
|
this.col = new Columns(settings);
|
||||||
|
this.columnsHandler =
|
||||||
|
AuthMeColumnsHandler.createForMySql(sql -> getConnection().prepareStatement(sql), settings);
|
||||||
this.sqlExtension = extensionsFactory.buildExtension(col);
|
this.sqlExtension = extensionsFactory.buildExtension(col);
|
||||||
this.poolSize = settings.getProperty(DatabaseSettings.MYSQL_POOL_SIZE);
|
this.poolSize = settings.getProperty(DatabaseSettings.MYSQL_POOL_SIZE);
|
||||||
this.maxLifetime = settings.getProperty(DatabaseSettings.MYSQL_CONNECTION_MAX_LIFETIME);
|
this.maxLifetime = settings.getProperty(DatabaseSettings.MYSQL_CONNECTION_MAX_LIFETIME);
|
||||||
@ -278,20 +284,13 @@ public class MySQL implements DataSource {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HashedPassword getPassword(String user) {
|
public HashedPassword getPassword(String user) {
|
||||||
boolean useSalt = !col.SALT.isEmpty();
|
try {
|
||||||
String sql = "SELECT " + col.PASSWORD
|
DataSourceValues passwordResult = columnsHandler.retrieve(user, AuthMeColumns.PASSWORD, AuthMeColumns.SALT);
|
||||||
+ (useSalt ? ", " + col.SALT : "")
|
if (passwordResult.rowExists()) {
|
||||||
+ " FROM " + tableName + " WHERE " + col.NAME + "=?;";
|
return new HashedPassword(passwordResult.get(AuthMeColumns.PASSWORD), passwordResult.get(AuthMeColumns.SALT));
|
||||||
try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
|
|
||||||
pst.setString(1, user.toLowerCase());
|
|
||||||
try (ResultSet rs = pst.executeQuery()) {
|
|
||||||
if (rs.next()) {
|
|
||||||
return new HashedPassword(rs.getString(col.PASSWORD),
|
|
||||||
useSalt ? rs.getString(col.SALT) : null);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException e) {
|
||||||
logSqlException(ex);
|
logSqlException(e);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -371,33 +370,9 @@ public class MySQL implements DataSource {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean updatePassword(String user, HashedPassword password) {
|
public boolean updatePassword(String user, HashedPassword password) {
|
||||||
user = user.toLowerCase();
|
return columnsHandler.update(user,
|
||||||
try (Connection con = getConnection()) {
|
with(AuthMeColumns.PASSWORD, password.getHash())
|
||||||
boolean useSalt = !col.SALT.isEmpty();
|
.and(AuthMeColumns.SALT, password.getSalt()).build());
|
||||||
if (useSalt) {
|
|
||||||
String sql = String.format("UPDATE %s SET %s = ?, %s = ? WHERE %s = ?;",
|
|
||||||
tableName, col.PASSWORD, col.SALT, col.NAME);
|
|
||||||
try (PreparedStatement pst = con.prepareStatement(sql)) {
|
|
||||||
pst.setString(1, password.getHash());
|
|
||||||
pst.setString(2, password.getSalt());
|
|
||||||
pst.setString(3, user);
|
|
||||||
pst.executeUpdate();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
String sql = String.format("UPDATE %s SET %s = ? WHERE %s = ?;",
|
|
||||||
tableName, col.PASSWORD, col.NAME);
|
|
||||||
try (PreparedStatement pst = con.prepareStatement(sql)) {
|
|
||||||
pst.setString(1, password.getHash());
|
|
||||||
pst.setString(2, user);
|
|
||||||
pst.executeUpdate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sqlExtension.changePassword(user, password, con);
|
|
||||||
return true;
|
|
||||||
} catch (SQLException ex) {
|
|
||||||
logSqlException(ex);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -456,38 +431,14 @@ public class MySQL implements DataSource {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean updateQuitLoc(PlayerAuth auth) {
|
public boolean updateQuitLoc(PlayerAuth auth) {
|
||||||
String sql = "UPDATE " + tableName
|
return columnsHandler.update(auth,
|
||||||
+ " SET " + col.LASTLOC_X + " =?, " + col.LASTLOC_Y + "=?, " + col.LASTLOC_Z + "=?, "
|
AuthMeColumns.LOCATION_X, AuthMeColumns.LOCATION_Y, AuthMeColumns.LOCATION_Z,
|
||||||
+ col.LASTLOC_WORLD + "=?, " + col.LASTLOC_YAW + "=?, " + col.LASTLOC_PITCH + "=?"
|
AuthMeColumns.LOCATION_WORLD, AuthMeColumns.LOCATION_YAW, AuthMeColumns.LOCATION_PITCH);
|
||||||
+ " WHERE " + col.NAME + "=?;";
|
|
||||||
try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
|
|
||||||
pst.setDouble(1, auth.getQuitLocX());
|
|
||||||
pst.setDouble(2, auth.getQuitLocY());
|
|
||||||
pst.setDouble(3, auth.getQuitLocZ());
|
|
||||||
pst.setString(4, auth.getWorld());
|
|
||||||
pst.setFloat(5, auth.getYaw());
|
|
||||||
pst.setFloat(6, auth.getPitch());
|
|
||||||
pst.setString(7, auth.getNickname());
|
|
||||||
pst.executeUpdate();
|
|
||||||
return true;
|
|
||||||
} catch (SQLException ex) {
|
|
||||||
logSqlException(ex);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean updateEmail(PlayerAuth auth) {
|
public boolean updateEmail(PlayerAuth auth) {
|
||||||
String sql = "UPDATE " + tableName + " SET " + col.EMAIL + " =? WHERE " + col.NAME + "=?;";
|
return columnsHandler.update(auth, AuthMeColumns.EMAIL);
|
||||||
try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
|
|
||||||
pst.setString(1, auth.getEmail());
|
|
||||||
pst.setString(2, auth.getNickname());
|
|
||||||
pst.executeUpdate();
|
|
||||||
return true;
|
|
||||||
} catch (SQLException ex) {
|
|
||||||
logSqlException(ex);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -654,16 +605,7 @@ public class MySQL implements DataSource {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean updateRealName(String user, String realName) {
|
public boolean updateRealName(String user, String realName) {
|
||||||
String sql = "UPDATE " + tableName + " SET " + col.REAL_NAME + "=? WHERE " + col.NAME + "=?;";
|
return columnsHandler.update(user, AuthMeColumns.NICK_NAME, realName);
|
||||||
try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
|
|
||||||
pst.setString(1, realName);
|
|
||||||
pst.setString(2, user);
|
|
||||||
pst.executeUpdate();
|
|
||||||
return true;
|
|
||||||
} catch (SQLException ex) {
|
|
||||||
logSqlException(ex);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -1,8 +1,10 @@
|
|||||||
package fr.xephi.authme.datasource;
|
package fr.xephi.authme.datasource;
|
||||||
|
|
||||||
|
import ch.jalu.datasourcecolumns.data.DataSourceValues;
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import fr.xephi.authme.ConsoleLogger;
|
import fr.xephi.authme.ConsoleLogger;
|
||||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
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.security.crypts.HashedPassword;
|
||||||
import fr.xephi.authme.settings.Settings;
|
import fr.xephi.authme.settings.Settings;
|
||||||
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
||||||
@ -22,6 +24,7 @@ import java.util.HashSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
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.getNullableLong;
|
||||||
import static fr.xephi.authme.datasource.SqlDataSourceUtils.logSqlException;
|
import static fr.xephi.authme.datasource.SqlDataSourceUtils.logSqlException;
|
||||||
|
|
||||||
@ -37,6 +40,7 @@ public class SQLite implements DataSource {
|
|||||||
private final String tableName;
|
private final String tableName;
|
||||||
private final Columns col;
|
private final Columns col;
|
||||||
private Connection con;
|
private Connection con;
|
||||||
|
private AuthMeColumnsHandler columnsHandler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for SQLite.
|
* Constructor for SQLite.
|
||||||
@ -71,6 +75,7 @@ public class SQLite implements DataSource {
|
|||||||
this.tableName = settings.getProperty(DatabaseSettings.MYSQL_TABLE);
|
this.tableName = settings.getProperty(DatabaseSettings.MYSQL_TABLE);
|
||||||
this.col = new Columns(settings);
|
this.col = new Columns(settings);
|
||||||
this.con = connection;
|
this.con = connection;
|
||||||
|
this.columnsHandler = AuthMeColumnsHandler.createForSqlite(con, settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -220,20 +225,13 @@ public class SQLite implements DataSource {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HashedPassword getPassword(String user) {
|
public HashedPassword getPassword(String user) {
|
||||||
boolean useSalt = !col.SALT.isEmpty();
|
try {
|
||||||
String sql = "SELECT " + col.PASSWORD
|
DataSourceValues values = columnsHandler.retrieve(user, AuthMeColumns.PASSWORD, AuthMeColumns.SALT);
|
||||||
+ (useSalt ? ", " + col.SALT : "")
|
if (values.rowExists()) {
|
||||||
+ " FROM " + tableName + " WHERE " + col.NAME + "=?";
|
return new HashedPassword(values.get(AuthMeColumns.PASSWORD), values.get(AuthMeColumns.SALT));
|
||||||
try (PreparedStatement pst = con.prepareStatement(sql)) {
|
|
||||||
pst.setString(1, user);
|
|
||||||
try (ResultSet rs = pst.executeQuery()) {
|
|
||||||
if (rs.next()) {
|
|
||||||
return new HashedPassword(rs.getString(col.PASSWORD),
|
|
||||||
useSalt ? rs.getString(col.SALT) : null);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException e) {
|
||||||
logSqlException(ex);
|
logSqlException(e);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -305,25 +303,9 @@ public class SQLite implements DataSource {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean updatePassword(String user, HashedPassword password) {
|
public boolean updatePassword(String user, HashedPassword password) {
|
||||||
user = user.toLowerCase();
|
return columnsHandler.update(user,
|
||||||
boolean useSalt = !col.SALT.isEmpty();
|
with(AuthMeColumns.PASSWORD, password.getHash())
|
||||||
String sql = "UPDATE " + tableName + " SET " + col.PASSWORD + " = ?"
|
.and(AuthMeColumns.SALT, password.getSalt()).build());
|
||||||
+ (useSalt ? ", " + col.SALT + " = ?" : "")
|
|
||||||
+ " WHERE " + col.NAME + " = ?";
|
|
||||||
try (PreparedStatement pst = con.prepareStatement(sql)){
|
|
||||||
pst.setString(1, password.getHash());
|
|
||||||
if (useSalt) {
|
|
||||||
pst.setString(2, password.getSalt());
|
|
||||||
pst.setString(3, user);
|
|
||||||
} else {
|
|
||||||
pst.setString(2, user);
|
|
||||||
}
|
|
||||||
pst.executeUpdate();
|
|
||||||
return true;
|
|
||||||
} catch (SQLException ex) {
|
|
||||||
logSqlException(ex);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -392,38 +374,14 @@ public class SQLite implements DataSource {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean updateQuitLoc(PlayerAuth auth) {
|
public boolean updateQuitLoc(PlayerAuth auth) {
|
||||||
String sql = "UPDATE " + tableName + " SET "
|
return columnsHandler.update(auth,
|
||||||
+ col.LASTLOC_X + "=?, " + col.LASTLOC_Y + "=?, " + col.LASTLOC_Z + "=?, "
|
AuthMeColumns.LOCATION_X, AuthMeColumns.LOCATION_Y, AuthMeColumns.LOCATION_Z,
|
||||||
+ col.LASTLOC_WORLD + "=?, " + col.LASTLOC_YAW + "=?, " + col.LASTLOC_PITCH + "=? "
|
AuthMeColumns.LOCATION_WORLD, AuthMeColumns.LOCATION_YAW, AuthMeColumns.LOCATION_PITCH);
|
||||||
+ "WHERE " + col.NAME + "=?;";
|
|
||||||
try (PreparedStatement pst = con.prepareStatement(sql)) {
|
|
||||||
pst.setDouble(1, auth.getQuitLocX());
|
|
||||||
pst.setDouble(2, auth.getQuitLocY());
|
|
||||||
pst.setDouble(3, auth.getQuitLocZ());
|
|
||||||
pst.setString(4, auth.getWorld());
|
|
||||||
pst.setFloat(5, auth.getYaw());
|
|
||||||
pst.setFloat(6, auth.getPitch());
|
|
||||||
pst.setString(7, auth.getNickname());
|
|
||||||
pst.executeUpdate();
|
|
||||||
return true;
|
|
||||||
} catch (SQLException ex) {
|
|
||||||
logSqlException(ex);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean updateEmail(PlayerAuth auth) {
|
public boolean updateEmail(PlayerAuth auth) {
|
||||||
String sql = "UPDATE " + tableName + " SET " + col.EMAIL + "=? WHERE " + col.NAME + "=?;";
|
return columnsHandler.update(auth, AuthMeColumns.EMAIL);
|
||||||
try (PreparedStatement pst = con.prepareStatement(sql)) {
|
|
||||||
pst.setString(1, auth.getEmail());
|
|
||||||
pst.setString(2, auth.getNickname());
|
|
||||||
pst.executeUpdate();
|
|
||||||
return true;
|
|
||||||
} catch (SQLException ex) {
|
|
||||||
logSqlException(ex);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -583,16 +541,7 @@ public class SQLite implements DataSource {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean updateRealName(String user, String realName) {
|
public boolean updateRealName(String user, String realName) {
|
||||||
String sql = "UPDATE " + tableName + " SET " + col.REAL_NAME + "=? WHERE " + col.NAME + "=?;";
|
return columnsHandler.update(user, AuthMeColumns.NICK_NAME, realName);
|
||||||
try (PreparedStatement pst = con.prepareStatement(sql)) {
|
|
||||||
pst.setString(1, realName);
|
|
||||||
pst.setString(2, user);
|
|
||||||
pst.executeUpdate();
|
|
||||||
return true;
|
|
||||||
} catch (SQLException ex) {
|
|
||||||
logSqlException(ex);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -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<ColumnContext, String> internalHandler;
|
||||||
|
|
||||||
|
private AuthMeColumnsHandler(SqlColumnsHandler<ColumnContext, String> 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<ColumnContext, String> 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<ColumnContext, String> 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 <T> the column type
|
||||||
|
* @return true upon success, false otherwise
|
||||||
|
*/
|
||||||
|
public <T> boolean update(String name, AuthMeColumns<T> 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<ColumnContext> 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 <T> the column type
|
||||||
|
* @return the result of the lookup
|
||||||
|
*/
|
||||||
|
public <T> DataSourceValue<T> retrieve(String name, AuthMeColumns<T> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -5,6 +5,7 @@ import com.google.common.collect.ImmutableList;
|
|||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import fr.xephi.authme.data.captcha.CaptchaCodeStorage;
|
import fr.xephi.authme.data.captcha.CaptchaCodeStorage;
|
||||||
|
import fr.xephi.authme.datasource.AuthMeColumns;
|
||||||
import fr.xephi.authme.datasource.Columns;
|
import fr.xephi.authme.datasource.Columns;
|
||||||
import fr.xephi.authme.datasource.mysqlextensions.MySqlExtension;
|
import fr.xephi.authme.datasource.mysqlextensions.MySqlExtension;
|
||||||
import fr.xephi.authme.initialization.HasCleanup;
|
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(),
|
int.class, long.class, float.class, String.class, File.class, Enum.class, collectionsUnmodifiableList(),
|
||||||
Charset.class,
|
Charset.class,
|
||||||
/* AuthMe */
|
/* AuthMe */
|
||||||
Property.class, RegistrationMethod.class,
|
Property.class, RegistrationMethod.class, AuthMeColumns.class,
|
||||||
/* Guava */
|
/* Guava */
|
||||||
ImmutableMap.class, ImmutableList.class);
|
ImmutableMap.class, ImmutableList.class);
|
||||||
|
|
||||||
|
|||||||
@ -61,7 +61,7 @@ public abstract class AbstractDataSourceIntegrationTest {
|
|||||||
// when
|
// when
|
||||||
HashedPassword bobbyPassword = dataSource.getPassword("bobby");
|
HashedPassword bobbyPassword = dataSource.getPassword("bobby");
|
||||||
HashedPassword invalidPassword = dataSource.getPassword("doesNotExist");
|
HashedPassword invalidPassword = dataSource.getPassword("doesNotExist");
|
||||||
HashedPassword userPassword = dataSource.getPassword("user");
|
HashedPassword userPassword = dataSource.getPassword("User");
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(bobbyPassword, equalToHash("$SHA$11aa0706173d7272$dbba966"));
|
assertThat(bobbyPassword, equalToHash("$SHA$11aa0706173d7272$dbba966"));
|
||||||
@ -160,7 +160,8 @@ public abstract class AbstractDataSourceIntegrationTest {
|
|||||||
boolean response2 = dataSource.updatePassword("non-existent-name", new HashedPassword("sd"));
|
boolean response2 = dataSource.updatePassword("non-existent-name", new HashedPassword("sd"));
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(response1 && response2, equalTo(true));
|
assertThat(response1, equalTo(true));
|
||||||
|
assertThat(response2, equalTo(false)); // no record modified
|
||||||
assertThat(dataSource.getPassword("user"), equalToHash(newHash));
|
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"));
|
boolean response2 = dataSource.updatePassword("non-existent-name", new HashedPassword("asdfasdf", "a1f34ec"));
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(response1 && response2, equalTo(true));
|
assertThat(response1, equalTo(true));
|
||||||
|
assertThat(response2, equalTo(false)); // no record modified
|
||||||
assertThat(dataSource.getPassword("user"), equalToHash("new_hash"));
|
assertThat(dataSource.getPassword("user"), equalToHash("new_hash"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,7 +193,8 @@ public abstract class AbstractDataSourceIntegrationTest {
|
|||||||
boolean response2 = dataSource.updatePassword(invalidAuth);
|
boolean response2 = dataSource.updatePassword(invalidAuth);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(response1 && response2, equalTo(true));
|
assertThat(response1, equalTo(true));
|
||||||
|
assertThat(response2, equalTo(false)); // no record modified
|
||||||
assertThat(dataSource.getPassword("bobby"), equalToHash("tt", "cc"));
|
assertThat(dataSource.getPassword("bobby"), equalToHash("tt", "cc"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -273,7 +276,8 @@ public abstract class AbstractDataSourceIntegrationTest {
|
|||||||
boolean response2 = dataSource.updateEmail(invalidAuth);
|
boolean response2 = dataSource.updateEmail(invalidAuth);
|
||||||
|
|
||||||
// then
|
// 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")));
|
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");
|
boolean response2 = dataSource.updateRealName("notExists", "NOTEXISTS");
|
||||||
|
|
||||||
// then
|
// 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"));
|
assertThat(dataSource.getAuth("bobby"), hasAuthBasicData("bobby", "BOBBY", null, "123.45.67.89"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user