mirror of
https://github.com/TuxCoding/FastLogin.git
synced 2025-07-30 10:47:33 +02:00
@ -27,12 +27,14 @@ package com.github.games647.fastlogin.core.shared;
|
|||||||
|
|
||||||
import com.github.games647.craftapi.resolver.MojangResolver;
|
import com.github.games647.craftapi.resolver.MojangResolver;
|
||||||
import com.github.games647.craftapi.resolver.http.RotatingProxySelector;
|
import com.github.games647.craftapi.resolver.http.RotatingProxySelector;
|
||||||
import com.github.games647.fastlogin.core.AuthStorage;
|
import com.github.games647.fastlogin.core.storage.MySQLStorage;
|
||||||
|
import com.github.games647.fastlogin.core.storage.SQLStorage;
|
||||||
import com.github.games647.fastlogin.core.CommonUtil;
|
import com.github.games647.fastlogin.core.CommonUtil;
|
||||||
import com.github.games647.fastlogin.core.RateLimiter;
|
import com.github.games647.fastlogin.core.RateLimiter;
|
||||||
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
||||||
import com.github.games647.fastlogin.core.hooks.DefaultPasswordGenerator;
|
import com.github.games647.fastlogin.core.hooks.DefaultPasswordGenerator;
|
||||||
import com.github.games647.fastlogin.core.hooks.PasswordGenerator;
|
import com.github.games647.fastlogin.core.hooks.PasswordGenerator;
|
||||||
|
import com.github.games647.fastlogin.core.storage.SQLiteStorage;
|
||||||
import com.google.common.net.HostAndPort;
|
import com.google.common.net.HostAndPort;
|
||||||
import com.zaxxer.hikari.HikariConfig;
|
import com.zaxxer.hikari.HikariConfig;
|
||||||
|
|
||||||
@ -82,7 +84,7 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
|
|||||||
private final MojangResolver resolver = new MojangResolver();
|
private final MojangResolver resolver = new MojangResolver();
|
||||||
|
|
||||||
private Configuration config;
|
private Configuration config;
|
||||||
private AuthStorage storage;
|
private SQLStorage storage;
|
||||||
private RateLimiter rateLimiter;
|
private RateLimiter rateLimiter;
|
||||||
private PasswordGenerator<P> passwordGenerator = new DefaultPasswordGenerator<>();
|
private PasswordGenerator<P> passwordGenerator = new DefaultPasswordGenerator<>();
|
||||||
private AuthPlugin<P> authPlugin;
|
private AuthPlugin<P> authPlugin;
|
||||||
@ -169,7 +171,7 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
|
|||||||
return resolver;
|
return resolver;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AuthStorage getStorage() {
|
public SQLStorage getStorage() {
|
||||||
return storage;
|
return storage;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,26 +191,31 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean setupDatabase() {
|
public boolean setupDatabase() {
|
||||||
if (!checkDriver(config.getString("driver"))) {
|
String driver = config.getString("driver");
|
||||||
|
if (!checkDriver(driver)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
HikariConfig databaseConfig = new HikariConfig();
|
HikariConfig databaseConfig = new HikariConfig();
|
||||||
databaseConfig.setDriverClassName(config.getString("driver"));
|
databaseConfig.setDriverClassName(driver);
|
||||||
|
|
||||||
String host = config.get("host", "");
|
|
||||||
int port = config.get("port", 3306);
|
|
||||||
String database = config.getString("database");
|
String database = config.getString("database");
|
||||||
|
|
||||||
boolean useSSL = config.get("useSSL", false);
|
|
||||||
|
|
||||||
databaseConfig.setUsername(config.get("username", ""));
|
|
||||||
databaseConfig.setPassword(config.getString("password"));
|
|
||||||
|
|
||||||
databaseConfig.setConnectionTimeout(config.getInt("timeout", 30) * 1_000L);
|
databaseConfig.setConnectionTimeout(config.getInt("timeout", 30) * 1_000L);
|
||||||
databaseConfig.setMaxLifetime(config.getInt("lifetime", 30) * 1_000L);
|
databaseConfig.setMaxLifetime(config.getInt("lifetime", 30) * 1_000L);
|
||||||
|
|
||||||
storage = new AuthStorage(this, host, port, database, databaseConfig, useSSL);
|
if (driver.contains("sqlite")) {
|
||||||
|
storage = new SQLiteStorage(this, database, databaseConfig);
|
||||||
|
} else {
|
||||||
|
String host = config.get("host", "");
|
||||||
|
int port = config.get("port", 3306);
|
||||||
|
boolean useSSL = config.get("useSSL", false);
|
||||||
|
|
||||||
|
databaseConfig.setUsername(config.get("username", ""));
|
||||||
|
databaseConfig.setPassword(config.getString("password"));
|
||||||
|
storage = new MySQLStorage(this, host, port, database, databaseConfig, useSSL);
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
storage.createTables();
|
storage.createTables();
|
||||||
return true;
|
return true;
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.core.shared;
|
package com.github.games647.fastlogin.core.shared;
|
||||||
|
|
||||||
import com.github.games647.fastlogin.core.AuthStorage;
|
import com.github.games647.fastlogin.core.storage.SQLStorage;
|
||||||
import com.github.games647.fastlogin.core.StoredProfile;
|
import com.github.games647.fastlogin.core.StoredProfile;
|
||||||
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
|
||||||
import com.github.games647.fastlogin.core.shared.event.FastLoginAutoLoginEvent;
|
import com.github.games647.fastlogin.core.shared.event.FastLoginAutoLoginEvent;
|
||||||
@ -55,7 +55,7 @@ public abstract class ForceLoginManagement<P extends C, C, L extends LoginSessio
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
AuthStorage storage = core.getStorage();
|
SQLStorage storage = core.getStorage();
|
||||||
StoredProfile playerProfile = session.getProfile();
|
StoredProfile playerProfile = session.getProfile();
|
||||||
try {
|
try {
|
||||||
if (isOnlineMode()) {
|
if (isOnlineMode()) {
|
||||||
|
@ -0,0 +1,15 @@
|
|||||||
|
package com.github.games647.fastlogin.core.storage;
|
||||||
|
|
||||||
|
import com.github.games647.fastlogin.core.StoredProfile;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public interface AuthStorage {
|
||||||
|
StoredProfile loadProfile(String name);
|
||||||
|
|
||||||
|
StoredProfile loadProfile(UUID uuid);
|
||||||
|
|
||||||
|
void save(StoredProfile playerProfile);
|
||||||
|
|
||||||
|
void close();
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
package com.github.games647.fastlogin.core.storage;
|
||||||
|
|
||||||
|
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
||||||
|
import com.zaxxer.hikari.HikariConfig;
|
||||||
|
|
||||||
|
public class MySQLStorage extends SQLStorage {
|
||||||
|
|
||||||
|
public MySQLStorage(FastLoginCore<?, ?, ?> core, String host, int port, String database, HikariConfig config, boolean useSSL) {
|
||||||
|
super(core,
|
||||||
|
"mysql://" + host + ':' + port + '/' + database,
|
||||||
|
setParams(config, useSSL));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static HikariConfig setParams(HikariConfig config, boolean useSSL) {
|
||||||
|
// Require SSL on the server if requested in config - this will also verify certificate
|
||||||
|
// Those values are deprecated in favor of sslMode
|
||||||
|
config.addDataSourceProperty("useSSL", useSSL);
|
||||||
|
config.addDataSourceProperty("requireSSL", useSSL);
|
||||||
|
|
||||||
|
// prefer encrypted if possible
|
||||||
|
config.addDataSourceProperty("sslMode", "PREFERRED");
|
||||||
|
|
||||||
|
// adding paranoid hides hostname, username, version and so
|
||||||
|
// could be useful for hiding server details
|
||||||
|
config.addDataSourceProperty("paranoid", true);
|
||||||
|
|
||||||
|
// enable MySQL specific optimizations
|
||||||
|
// disabled by default - will return the same prepared statement instance
|
||||||
|
config.addDataSourceProperty("cachePrepStmts", true);
|
||||||
|
// default prepStmtCacheSize 25 - amount of cached statements
|
||||||
|
config.addDataSourceProperty("prepStmtCacheSize", 250);
|
||||||
|
// default prepStmtCacheSqlLimit 256 - length of SQL
|
||||||
|
config.addDataSourceProperty("prepStmtCacheSqlLimit", 2048);
|
||||||
|
// default false - available in newer versions caches the statements server-side
|
||||||
|
config.addDataSourceProperty("useServerPrepStmts", true);
|
||||||
|
// default false - prefer use of local values for autocommit and
|
||||||
|
// transaction isolation (alwaysSendSetIsolation) should only be enabled if always use the set* methods
|
||||||
|
// instead of raw SQL
|
||||||
|
// https://forums.mysql.com/read.php?39,626495,626512
|
||||||
|
config.addDataSourceProperty("useLocalSessionState", true);
|
||||||
|
// rewrite batched statements to a single statement, adding them behind each other
|
||||||
|
// only useful for addBatch statements and inserts
|
||||||
|
config.addDataSourceProperty("rewriteBatchedStatements", true);
|
||||||
|
// cache result metadata
|
||||||
|
config.addDataSourceProperty("cacheResultSetMetadata", true);
|
||||||
|
// cache results of show variables and collation per URL
|
||||||
|
config.addDataSourceProperty("cacheServerConfiguration", true);
|
||||||
|
// default false - set auto commit only if not matching
|
||||||
|
config.addDataSourceProperty("elideSetAutoCommits", true);
|
||||||
|
|
||||||
|
// default true - internal timers for idle calculation -> removes System.getCurrentTimeMillis call per query
|
||||||
|
// Some platforms are slow on this and it could affect the throughput about 3% according to MySQL
|
||||||
|
// performance gems presentation
|
||||||
|
// In our case it can be useful to see the time in error messages
|
||||||
|
// config.addDataSourceProperty("maintainTimeStats", false);
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
}
|
@ -23,9 +23,10 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.github.games647.fastlogin.core;
|
package com.github.games647.fastlogin.core.storage;
|
||||||
|
|
||||||
import com.github.games647.craftapi.UUIDAdapter;
|
import com.github.games647.craftapi.UUIDAdapter;
|
||||||
|
import com.github.games647.fastlogin.core.StoredProfile;
|
||||||
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
||||||
import com.zaxxer.hikari.HikariConfig;
|
import com.zaxxer.hikari.HikariConfig;
|
||||||
import com.zaxxer.hikari.HikariDataSource;
|
import com.zaxxer.hikari.HikariDataSource;
|
||||||
@ -42,23 +43,34 @@ import java.util.concurrent.ThreadFactory;
|
|||||||
|
|
||||||
import static java.sql.Statement.RETURN_GENERATED_KEYS;
|
import static java.sql.Statement.RETURN_GENERATED_KEYS;
|
||||||
|
|
||||||
public class AuthStorage {
|
public abstract class SQLStorage implements AuthStorage {
|
||||||
|
|
||||||
private static final String PREMIUM_TABLE = "premium";
|
private static final String JDBC_PROTOCOL = "jdbc:";
|
||||||
|
|
||||||
private static final String LOAD_BY_NAME = "SELECT * FROM `" + PREMIUM_TABLE + "` WHERE `Name`=? LIMIT 1";
|
protected static final String PREMIUM_TABLE = "premium";
|
||||||
private static final String LOAD_BY_UUID = "SELECT * FROM `" + PREMIUM_TABLE + "` WHERE `UUID`=? LIMIT 1";
|
protected static final String CREATE_TABLE_STMT = "CREATE TABLE IF NOT EXISTS `" + PREMIUM_TABLE + "` ("
|
||||||
private static final String INSERT_PROFILE = "INSERT INTO `" + PREMIUM_TABLE
|
+ "`UserID` INTEGER PRIMARY KEY AUTO_INCREMENT, "
|
||||||
|
+ "`UUID` CHAR(36), "
|
||||||
|
+ "`Name` VARCHAR(16) NOT NULL, "
|
||||||
|
+ "`Premium` BOOLEAN NOT NULL, "
|
||||||
|
+ "`LastIp` VARCHAR(255) NOT NULL, "
|
||||||
|
+ "`LastLogin` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, "
|
||||||
|
//the premium shouldn't steal the cracked account by changing the name
|
||||||
|
+ "UNIQUE (`Name`) "
|
||||||
|
+ ')';
|
||||||
|
|
||||||
|
protected static final String LOAD_BY_NAME = "SELECT * FROM `" + PREMIUM_TABLE + "` WHERE `Name`=? LIMIT 1";
|
||||||
|
protected static final String LOAD_BY_UUID = "SELECT * FROM `" + PREMIUM_TABLE + "` WHERE `UUID`=? LIMIT 1";
|
||||||
|
protected static final String INSERT_PROFILE = "INSERT INTO `" + PREMIUM_TABLE
|
||||||
+ "` (`UUID`, `Name`, `Premium`, `LastIp`) " + "VALUES (?, ?, ?, ?) ";
|
+ "` (`UUID`, `Name`, `Premium`, `LastIp`) " + "VALUES (?, ?, ?, ?) ";
|
||||||
// limit not necessary here, because it's unique
|
// limit not necessary here, because it's unique
|
||||||
private static final String UPDATE_PROFILE = "UPDATE `" + PREMIUM_TABLE
|
protected static final String UPDATE_PROFILE = "UPDATE `" + PREMIUM_TABLE
|
||||||
+ "` SET `UUID`=?, `Name`=?, `Premium`=?, `LastIp`=?, `LastLogin`=CURRENT_TIMESTAMP WHERE `UserID`=?";
|
+ "` SET `UUID`=?, `Name`=?, `Premium`=?, `LastIp`=?, `LastLogin`=CURRENT_TIMESTAMP WHERE `UserID`=?";
|
||||||
|
|
||||||
private final FastLoginCore<?, ?, ?> core;
|
protected final FastLoginCore<?, ?, ?> core;
|
||||||
private final HikariDataSource dataSource;
|
protected final HikariDataSource dataSource;
|
||||||
|
|
||||||
public AuthStorage(FastLoginCore<?, ?, ?> core, String host, int port, String databasePath,
|
public SQLStorage(FastLoginCore<?, ?, ?> core, String jdbcURL, HikariConfig config) {
|
||||||
HikariConfig config, boolean useSSL) {
|
|
||||||
this.core = core;
|
this.core = core;
|
||||||
config.setPoolName(core.getPlugin().getName());
|
config.setPoolName(core.getPlugin().getName());
|
||||||
|
|
||||||
@ -67,68 +79,7 @@ public class AuthStorage {
|
|||||||
config.setThreadFactory(platformThreadFactory);
|
config.setThreadFactory(platformThreadFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
String jdbcUrl = "jdbc:";
|
config.setJdbcUrl(JDBC_PROTOCOL + jdbcURL);
|
||||||
if (config.getDriverClassName().contains("sqlite")) {
|
|
||||||
String pluginFolder = core.getPlugin().getPluginFolder().toAbsolutePath().toString();
|
|
||||||
databasePath = databasePath.replace("{pluginDir}", pluginFolder);
|
|
||||||
|
|
||||||
jdbcUrl += "sqlite://" + databasePath;
|
|
||||||
config.setConnectionTestQuery("SELECT 1");
|
|
||||||
config.setMaximumPoolSize(1);
|
|
||||||
|
|
||||||
//a try to fix https://www.spigotmc.org/threads/fastlogin.101192/page-26#post-1874647
|
|
||||||
// format strings retrieved by the timestamp column to match them from MySQL
|
|
||||||
config.addDataSourceProperty("date_string_format", "yyyy-MM-dd HH:mm:ss");
|
|
||||||
|
|
||||||
// TODO: test first for compatibility
|
|
||||||
// config.addDataSourceProperty("date_precision", "seconds");
|
|
||||||
} else {
|
|
||||||
jdbcUrl += "mysql://" + host + ':' + port + '/' + databasePath;
|
|
||||||
|
|
||||||
// Require SSL on the server if requested in config - this will also verify certificate
|
|
||||||
// Those values are deprecated in favor of sslMode
|
|
||||||
config.addDataSourceProperty("useSSL", useSSL);
|
|
||||||
config.addDataSourceProperty("requireSSL", useSSL);
|
|
||||||
|
|
||||||
// prefer encrypted if possible
|
|
||||||
config.addDataSourceProperty("sslMode", "PREFERRED");
|
|
||||||
|
|
||||||
// adding paranoid hides hostname, username, version and so
|
|
||||||
// could be useful for hiding server details
|
|
||||||
config.addDataSourceProperty("paranoid", true);
|
|
||||||
|
|
||||||
// enable MySQL specific optimizations
|
|
||||||
// disabled by default - will return the same prepared statement instance
|
|
||||||
config.addDataSourceProperty("cachePrepStmts", true);
|
|
||||||
// default prepStmtCacheSize 25 - amount of cached statements
|
|
||||||
config.addDataSourceProperty("prepStmtCacheSize", 250);
|
|
||||||
// default prepStmtCacheSqlLimit 256 - length of SQL
|
|
||||||
config.addDataSourceProperty("prepStmtCacheSqlLimit", 2048);
|
|
||||||
// default false - available in newer versions caches the statements server-side
|
|
||||||
config.addDataSourceProperty("useServerPrepStmts", true);
|
|
||||||
// default false - prefer use of local values for autocommit and
|
|
||||||
// transaction isolation (alwaysSendSetIsolation) should only be enabled if always use the set* methods
|
|
||||||
// instead of raw SQL
|
|
||||||
// https://forums.mysql.com/read.php?39,626495,626512
|
|
||||||
config.addDataSourceProperty("useLocalSessionState", true);
|
|
||||||
// rewrite batched statements to a single statement, adding them behind each other
|
|
||||||
// only useful for addBatch statements and inserts
|
|
||||||
config.addDataSourceProperty("rewriteBatchedStatements", true);
|
|
||||||
// cache result metadata
|
|
||||||
config.addDataSourceProperty("cacheResultSetMetadata", true);
|
|
||||||
// cache results of show variables and collation per URL
|
|
||||||
config.addDataSourceProperty("cacheServerConfiguration", true);
|
|
||||||
// default false - set auto commit only if not matching
|
|
||||||
config.addDataSourceProperty("elideSetAutoCommits", true);
|
|
||||||
|
|
||||||
// default true - internal timers for idle calculation -> removes System.getCurrentTimeMillis call per query
|
|
||||||
// Some platforms are slow on this and it could affect the throughput about 3% according to MySQL
|
|
||||||
// performance gems presentation
|
|
||||||
// In our case it can be useful to see the time in error messages
|
|
||||||
// config.addDataSourceProperty("maintainTimeStats", false);
|
|
||||||
}
|
|
||||||
|
|
||||||
config.setJdbcUrl(jdbcUrl);
|
|
||||||
this.dataSource = new HikariDataSource(config);
|
this.dataSource = new HikariDataSource(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,28 +87,15 @@ public class AuthStorage {
|
|||||||
// choose surrogate PK(ID), because UUID can be null for offline players
|
// choose surrogate PK(ID), because UUID can be null for offline players
|
||||||
// if UUID is always Premium UUID we would have to update offline player entries on insert
|
// if UUID is always Premium UUID we would have to update offline player entries on insert
|
||||||
// name cannot be PK, because it can be changed for premium players
|
// name cannot be PK, because it can be changed for premium players
|
||||||
String createDataStmt = "CREATE TABLE IF NOT EXISTS `" + PREMIUM_TABLE + "` ("
|
|
||||||
+ "`UserID` INTEGER PRIMARY KEY AUTO_INCREMENT, "
|
|
||||||
+ "`UUID` CHAR(36), "
|
|
||||||
+ "`Name` VARCHAR(16) NOT NULL, "
|
|
||||||
+ "`Premium` BOOLEAN NOT NULL, "
|
|
||||||
+ "`LastIp` VARCHAR(255) NOT NULL, "
|
|
||||||
+ "`LastLogin` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, "
|
|
||||||
//the premium shouldn't steal the cracked account by changing the name
|
|
||||||
+ "UNIQUE (`Name`) "
|
|
||||||
+ ')';
|
|
||||||
|
|
||||||
if (dataSource.getJdbcUrl().contains("sqlite")) {
|
|
||||||
createDataStmt = createDataStmt.replace("AUTO_INCREMENT", "AUTOINCREMENT");
|
|
||||||
}
|
|
||||||
|
|
||||||
//todo: add unique uuid index usage
|
//todo: add unique uuid index usage
|
||||||
try (Connection con = dataSource.getConnection();
|
try (Connection con = dataSource.getConnection();
|
||||||
Statement createStmt = con.createStatement()) {
|
Statement createStmt = con.createStatement()) {
|
||||||
createStmt.executeUpdate(createDataStmt);
|
createStmt.executeUpdate(CREATE_TABLE_STMT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public StoredProfile loadProfile(String name) {
|
public StoredProfile loadProfile(String name) {
|
||||||
try (Connection con = dataSource.getConnection();
|
try (Connection con = dataSource.getConnection();
|
||||||
PreparedStatement loadStmt = con.prepareStatement(LOAD_BY_NAME)
|
PreparedStatement loadStmt = con.prepareStatement(LOAD_BY_NAME)
|
||||||
@ -174,6 +112,7 @@ public class AuthStorage {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public StoredProfile loadProfile(UUID uuid) {
|
public StoredProfile loadProfile(UUID uuid) {
|
||||||
try (Connection con = dataSource.getConnection();
|
try (Connection con = dataSource.getConnection();
|
||||||
PreparedStatement loadStmt = con.prepareStatement(LOAD_BY_UUID)) {
|
PreparedStatement loadStmt = con.prepareStatement(LOAD_BY_UUID)) {
|
||||||
@ -205,6 +144,7 @@ public class AuthStorage {
|
|||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void save(StoredProfile playerProfile) {
|
public void save(StoredProfile playerProfile) {
|
||||||
try (Connection con = dataSource.getConnection()) {
|
try (Connection con = dataSource.getConnection()) {
|
||||||
String uuid = playerProfile.getOptId().map(UUIDAdapter::toMojangId).orElse(null);
|
String uuid = playerProfile.getOptId().map(UUIDAdapter::toMojangId).orElse(null);
|
||||||
@ -245,6 +185,7 @@ public class AuthStorage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
dataSource.close();
|
dataSource.close();
|
||||||
}
|
}
|
@ -0,0 +1,82 @@
|
|||||||
|
package com.github.games647.fastlogin.core.storage;
|
||||||
|
|
||||||
|
import com.github.games647.fastlogin.core.StoredProfile;
|
||||||
|
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
||||||
|
import com.github.games647.fastlogin.core.shared.PlatformPlugin;
|
||||||
|
import com.zaxxer.hikari.HikariConfig;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Statement;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.locks.Lock;
|
||||||
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
|
public class SQLiteStorage extends SQLStorage {
|
||||||
|
|
||||||
|
private final Lock lock = new ReentrantLock();
|
||||||
|
|
||||||
|
public SQLiteStorage(FastLoginCore<?, ?, ?> core, String databasePath, HikariConfig config) {
|
||||||
|
super(core,
|
||||||
|
"sqlite://" + replacePathVariables(core.getPlugin(), databasePath),
|
||||||
|
setParams(config));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static HikariConfig setParams(HikariConfig config) {
|
||||||
|
config.setConnectionTestQuery("SELECT 1");
|
||||||
|
config.setMaximumPoolSize(1);
|
||||||
|
|
||||||
|
//a try to fix https://www.spigotmc.org/threads/fastlogin.101192/page-26#post-1874647
|
||||||
|
// format strings retrieved by the timestamp column to match them from MySQL
|
||||||
|
config.addDataSourceProperty("date_string_format", "yyyy-MM-dd HH:mm:ss");
|
||||||
|
|
||||||
|
// TODO: test first for compatibility
|
||||||
|
// config.addDataSourceProperty("date_precision", "seconds");
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StoredProfile loadProfile(String name) {
|
||||||
|
lock.lock();
|
||||||
|
try {
|
||||||
|
return super.loadProfile(name);
|
||||||
|
} finally {
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StoredProfile loadProfile(UUID uuid) {
|
||||||
|
lock.lock();
|
||||||
|
try {
|
||||||
|
return super.loadProfile(uuid);
|
||||||
|
} finally {
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void save(StoredProfile playerProfile) {
|
||||||
|
lock.lock();
|
||||||
|
try {
|
||||||
|
super.save(playerProfile);
|
||||||
|
} finally {
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void createTables() throws SQLException {
|
||||||
|
try (Connection con = dataSource.getConnection();
|
||||||
|
Statement createStmt = con.createStatement()) {
|
||||||
|
// SQLite has a different syntax for auto increment
|
||||||
|
createStmt.executeUpdate(CREATE_TABLE_STMT.replace("AUTO_INCREMENT", "AUTOINCREMENT"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String replacePathVariables(PlatformPlugin<?> plugin, String input) {
|
||||||
|
String pluginFolder = plugin.getPluginFolder().toAbsolutePath().toString();
|
||||||
|
return input.replace("{pluginDir}", pluginFolder);
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user