Remove duplicate column initialization code, add datasource integration tests
- Drop initialization of all columns on table create in favor of checking each column individually. This is slower but guarantees that each column is only defined once in the code. Columns are only created once so having clean code outweighs performance. - Write more datasource integration tests
This commit is contained in:
@@ -3,14 +3,12 @@ package fr.xephi.authme.datasource;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
import com.zaxxer.hikari.pool.HikariPool.PoolInitializationException;
|
||||
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.cache.auth.PlayerAuth;
|
||||
import fr.xephi.authme.security.HashAlgorithm;
|
||||
import fr.xephi.authme.security.crypts.HashedPassword;
|
||||
import fr.xephi.authme.security.crypts.XFBCRYPT;
|
||||
import fr.xephi.authme.settings.NewSetting;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
||||
import fr.xephi.authme.settings.properties.HooksSettings;
|
||||
import fr.xephi.authme.settings.properties.SecuritySettings;
|
||||
@@ -69,7 +67,7 @@ public class MySQL implements DataSource {
|
||||
|
||||
// Initialize the database
|
||||
try {
|
||||
setupConnection();
|
||||
checkTablesAndColumns();
|
||||
} catch (SQLException e) {
|
||||
close();
|
||||
ConsoleLogger.logException("Can't initialize the MySQL database:", e);
|
||||
@@ -140,24 +138,13 @@ public class MySQL implements DataSource {
|
||||
return ds.getConnection();
|
||||
}
|
||||
|
||||
private void setupConnection() throws SQLException {
|
||||
private void checkTablesAndColumns() throws SQLException {
|
||||
try (Connection con = getConnection(); Statement st = con.createStatement()) {
|
||||
// Create table if not exists.
|
||||
// Create table with ID column if it doesn't exist
|
||||
String sql = "CREATE TABLE IF NOT EXISTS " + tableName + " ("
|
||||
+ col.ID + " MEDIUMINT(8) UNSIGNED AUTO_INCREMENT,"
|
||||
+ col.NAME + " VARCHAR(255) NOT NULL UNIQUE,"
|
||||
+ col.REAL_NAME + " VARCHAR(255) NOT NULL,"
|
||||
+ col.PASSWORD + " VARCHAR(255) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,"
|
||||
+ col.IP + " VARCHAR(40) CHARACTER SET ascii COLLATE ascii_bin NOT NULL DEFAULT '127.0.0.1',"
|
||||
+ col.LAST_LOGIN + " BIGINT NOT NULL DEFAULT 0,"
|
||||
+ col.LASTLOC_X + " DOUBLE NOT NULL DEFAULT '0.0',"
|
||||
+ col.LASTLOC_Y + " DOUBLE NOT NULL DEFAULT '0.0',"
|
||||
+ col.LASTLOC_Z + " DOUBLE NOT NULL DEFAULT '0.0',"
|
||||
+ col.LASTLOC_WORLD + " VARCHAR(255) NOT NULL DEFAULT '" + Settings.defaultWorld + "',"
|
||||
+ col.EMAIL + " VARCHAR(255) DEFAULT 'your@email.com',"
|
||||
+ col.IS_LOGGED + " SMALLINT NOT NULL DEFAULT '0',"
|
||||
+ "PRIMARY KEY (" + col.ID + ")"
|
||||
+ ") CHARACTER SET = utf8";
|
||||
+ ") CHARACTER SET = utf8;";
|
||||
st.executeUpdate(sql);
|
||||
|
||||
DatabaseMetaData md = con.getMetaData();
|
||||
@@ -177,8 +164,7 @@ public class MySQL implements DataSource {
|
||||
}
|
||||
|
||||
if (!col.SALT.isEmpty() && isColumnMissing(md, col.SALT)) {
|
||||
st.executeUpdate("ALTER TABLE " + tableName
|
||||
+ " ADD COLUMN " + col.SALT + " VARCHAR(255);");
|
||||
st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN " + col.SALT + " VARCHAR(255);");
|
||||
}
|
||||
|
||||
if (isColumnMissing(md, col.IP)) {
|
||||
@@ -219,8 +205,6 @@ public class MySQL implements DataSource {
|
||||
st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN "
|
||||
+ col.IS_LOGGED + " SMALLINT NOT NULL DEFAULT '0' AFTER " + col.EMAIL);
|
||||
}
|
||||
|
||||
st.close();
|
||||
}
|
||||
ConsoleLogger.info("MySQL setup finished");
|
||||
}
|
||||
|
||||
@@ -5,11 +5,11 @@ import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.cache.auth.PlayerAuth;
|
||||
import fr.xephi.authme.security.crypts.HashedPassword;
|
||||
import fr.xephi.authme.settings.NewSetting;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
||||
import fr.xephi.authme.util.StringUtils;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
@@ -69,67 +69,73 @@ public class SQLite implements DataSource {
|
||||
this.con = DriverManager.getConnection("jdbc:sqlite:plugins/AuthMe/" + database + ".db");
|
||||
}
|
||||
|
||||
private void setup() throws SQLException {
|
||||
Statement st = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
st = con.createStatement();
|
||||
st.executeUpdate("CREATE TABLE IF NOT EXISTS " + tableName + " (" + col.ID + " INTEGER AUTO_INCREMENT," + col.NAME + " VARCHAR(255) NOT NULL UNIQUE," + col.PASSWORD + " VARCHAR(255) NOT NULL," + col.IP + " VARCHAR(40) NOT NULL," + col.LAST_LOGIN + " BIGINT," + col.LASTLOC_X + " DOUBLE NOT NULL DEFAULT '0.0'," + col.LASTLOC_Y + " DOUBLE NOT NULL DEFAULT '0.0'," + col.LASTLOC_Z + " DOUBLE NOT NULL DEFAULT '0.0'," + col.LASTLOC_WORLD + " VARCHAR(255) NOT NULL DEFAULT '" + Settings.defaultWorld + "'," + col.EMAIL + " VARCHAR(255) DEFAULT 'your@email.com'," + "CONSTRAINT table_const_prim PRIMARY KEY (" + col.ID + "));");
|
||||
rs = con.getMetaData().getColumns(null, null, tableName, col.PASSWORD);
|
||||
if (!rs.next()) {
|
||||
st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN " + col.PASSWORD + " VARCHAR(255) NOT NULL;");
|
||||
@VisibleForTesting
|
||||
protected void setup() throws SQLException {
|
||||
try (Statement st = con.createStatement()) {
|
||||
// Note: cannot add unique fields later on in SQLite, so we add it on initialization
|
||||
st.executeUpdate("CREATE TABLE IF NOT EXISTS " + tableName + " ("
|
||||
+ col.ID + " INTEGER AUTO_INCREMENT, "
|
||||
+ col.NAME + " VARCHAR(255) NOT NULL UNIQUE, "
|
||||
+ "CONSTRAINT table_const_prim PRIMARY KEY (" + col.ID + "));");
|
||||
|
||||
DatabaseMetaData md = con.getMetaData();
|
||||
|
||||
if (isColumnMissing(md, col.REAL_NAME)) {
|
||||
st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN "
|
||||
+ col.REAL_NAME + " VARCHAR(255) NOT NULL DEFAULT 'Player';");
|
||||
}
|
||||
rs.close();
|
||||
if (!col.SALT.isEmpty()) {
|
||||
rs = con.getMetaData().getColumns(null, null, tableName, col.SALT);
|
||||
if (!rs.next()) {
|
||||
st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN " + col.SALT + " VARCHAR(255);");
|
||||
}
|
||||
rs.close();
|
||||
|
||||
if (isColumnMissing(md, col.PASSWORD)) {
|
||||
st.executeUpdate("ALTER TABLE " + tableName
|
||||
+ " ADD COLUMN " + col.PASSWORD + " VARCHAR(255) NOT NULL DEFAULT '';");
|
||||
}
|
||||
rs = con.getMetaData().getColumns(null, null, tableName, col.IP);
|
||||
if (!rs.next()) {
|
||||
st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN " + col.IP + " VARCHAR(40) NOT NULL;");
|
||||
|
||||
if (!col.SALT.isEmpty() && isColumnMissing(md, col.SALT)) {
|
||||
st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN " + col.SALT + " VARCHAR(255);");
|
||||
}
|
||||
rs.close();
|
||||
rs = con.getMetaData().getColumns(null, null, tableName, col.LAST_LOGIN);
|
||||
if (!rs.next()) {
|
||||
st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN " + col.LAST_LOGIN + " TIMESTAMP DEFAULT current_timestamp;");
|
||||
|
||||
if (isColumnMissing(md, col.IP)) {
|
||||
st.executeUpdate("ALTER TABLE " + tableName
|
||||
+ " ADD COLUMN " + col.IP + " VARCHAR(40) NOT NULL DEFAULT '';");
|
||||
}
|
||||
rs.close();
|
||||
rs = con.getMetaData().getColumns(null, null, tableName, col.LASTLOC_X);
|
||||
if (!rs.next()) {
|
||||
st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN " + col.LASTLOC_X + " DOUBLE NOT NULL DEFAULT '0.0';");
|
||||
st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN " + col.LASTLOC_Y + " DOUBLE NOT NULL DEFAULT '0.0';");
|
||||
st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN " + col.LASTLOC_Z + " DOUBLE NOT NULL DEFAULT '0.0';");
|
||||
|
||||
if (isColumnMissing(md, col.LAST_LOGIN)) {
|
||||
st.executeUpdate("ALTER TABLE " + tableName
|
||||
+ " ADD COLUMN " + col.LAST_LOGIN + " TIMESTAMP;");
|
||||
}
|
||||
rs.close();
|
||||
rs = con.getMetaData().getColumns(null, null, tableName, col.LASTLOC_WORLD);
|
||||
if (!rs.next()) {
|
||||
st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN " + col.LASTLOC_WORLD + " VARCHAR(255) NOT NULL DEFAULT 'world';");
|
||||
|
||||
if (isColumnMissing(md, col.LASTLOC_X)) {
|
||||
st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN " + col.LASTLOC_X
|
||||
+ " DOUBLE NOT NULL DEFAULT '0.0';");
|
||||
st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN " + col.LASTLOC_Y
|
||||
+ " DOUBLE NOT NULL DEFAULT '0.0';");
|
||||
st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN " + col.LASTLOC_Z
|
||||
+ " DOUBLE NOT NULL DEFAULT '0.0';");
|
||||
}
|
||||
rs.close();
|
||||
rs = con.getMetaData().getColumns(null, null, tableName, col.EMAIL);
|
||||
if (!rs.next()) {
|
||||
st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN " + col.EMAIL + " VARCHAR(255) DEFAULT 'your@email.com';");
|
||||
|
||||
if (isColumnMissing(md, col.LASTLOC_WORLD)) {
|
||||
st.executeUpdate("ALTER TABLE " + tableName
|
||||
+ " ADD COLUMN " + col.LASTLOC_WORLD + " VARCHAR(255) NOT NULL DEFAULT 'world';");
|
||||
}
|
||||
rs.close();
|
||||
rs = con.getMetaData().getColumns(null, null, tableName, col.IS_LOGGED);
|
||||
if (!rs.next()) {
|
||||
|
||||
if (isColumnMissing(md, col.EMAIL)) {
|
||||
st.executeUpdate("ALTER TABLE " + tableName
|
||||
+ " ADD COLUMN " + col.EMAIL + " VARCHAR(255) DEFAULT 'your@email.com';");
|
||||
}
|
||||
|
||||
if (isColumnMissing(md, col.IS_LOGGED)) {
|
||||
st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN " + col.IS_LOGGED + " INT DEFAULT '0';");
|
||||
}
|
||||
rs.close();
|
||||
rs = con.getMetaData().getColumns(null, null, tableName, col.REAL_NAME);
|
||||
if (!rs.next()) {
|
||||
st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN " + col.REAL_NAME + " VARCHAR(255) NOT NULL DEFAULT 'Player';");
|
||||
}
|
||||
} finally {
|
||||
close(rs);
|
||||
close(st);
|
||||
}
|
||||
ConsoleLogger.info("SQLite Setup finished");
|
||||
}
|
||||
|
||||
private boolean isColumnMissing(DatabaseMetaData metaData, String columnName) throws SQLException {
|
||||
try (ResultSet rs = metaData.getColumns(null, null, tableName, columnName)) {
|
||||
return !rs.next();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
close(con);
|
||||
@@ -146,7 +152,7 @@ public class SQLite implements DataSource {
|
||||
PreparedStatement pst = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
pst = con.prepareStatement("SELECT * FROM " + tableName + " WHERE LOWER(" + col.NAME + ")=LOWER(?);");
|
||||
pst = con.prepareStatement("SELECT 1 FROM " + tableName + " WHERE LOWER(" + col.NAME + ")=LOWER(?);");
|
||||
pst.setString(1, user);
|
||||
rs = pst.executeQuery();
|
||||
return rs.next();
|
||||
|
||||
@@ -18,20 +18,16 @@ public final class Settings {
|
||||
public static List<String> getUnrestrictedName;
|
||||
public static boolean isPermissionCheckEnabled;
|
||||
public static boolean isTeleportToSpawnEnabled;
|
||||
public static boolean isSessionsEnabled;
|
||||
public static boolean isAllowRestrictedIp;
|
||||
public static boolean isSaveQuitLocationEnabled;
|
||||
public static boolean protectInventoryBeforeLogInEnabled;
|
||||
public static boolean isStopEnabled;
|
||||
public static boolean reloadSupport;
|
||||
public static boolean noTeleport;
|
||||
public static boolean isRemoveSpeedEnabled;
|
||||
public static String getUnloggedinGroup;
|
||||
public static String unRegisteredGroup;
|
||||
public static String getRegisteredGroup;
|
||||
public static String defaultWorld;
|
||||
public static String crazyloginFileName;
|
||||
public static int getSessionTimeout;
|
||||
public static int getNonActivatedGroup;
|
||||
private static FileConfiguration configFile;
|
||||
|
||||
@@ -48,10 +44,7 @@ public final class Settings {
|
||||
private static void loadVariables() {
|
||||
isPermissionCheckEnabled = load(PluginSettings.ENABLE_PERMISSION_CHECK);
|
||||
isTeleportToSpawnEnabled = load(RestrictionSettings.TELEPORT_UNAUTHED_TO_SPAWN);
|
||||
isSessionsEnabled = load(PluginSettings.SESSIONS_ENABLED);
|
||||
getSessionTimeout = configFile.getInt("settings.sessions.timeout", 10);
|
||||
isAllowRestrictedIp = load(RestrictionSettings.ENABLE_RESTRICTED_USERS);
|
||||
isRemoveSpeedEnabled = load(RestrictionSettings.REMOVE_SPEED);
|
||||
isSaveQuitLocationEnabled = load(RestrictionSettings.SAVE_QUIT_LOCATION);
|
||||
getUnloggedinGroup = load(SecuritySettings.UNLOGGEDIN_GROUP);
|
||||
getNonActivatedGroup = configFile.getInt("ExternalBoardOptions.nonActivedUserGroup", -1);
|
||||
@@ -63,7 +56,6 @@ public final class Settings {
|
||||
reloadSupport = configFile.getBoolean("Security.ReloadCommand.useReloadCommandSupport", true);
|
||||
defaultWorld = configFile.getString("Purge.defaultWorld", "world");
|
||||
noTeleport = load(RestrictionSettings.NO_TELEPORT);
|
||||
crazyloginFileName = configFile.getString("Converter.CrazyLogin.fileName", "accounts.db");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user