forked from TuxCoding/FastLogin
Add support for postgresql
This commit is contained in:
@ -117,10 +117,10 @@ Install the plugin on both platforms, that is proxy (BungeeCord or Velocity) and
|
|||||||
4. Activate ip forwarding in your proxy config
|
4. Activate ip forwarding in your proxy config
|
||||||
5. Check your database settings in the config of FastLogin on your proxy
|
5. Check your database settings in the config of FastLogin on your proxy
|
||||||
* The proxies only ship with a limited set of drivers where Spigot supports more. Therefore, these are supported:
|
* The proxies only ship with a limited set of drivers where Spigot supports more. Therefore, these are supported:
|
||||||
* BungeeCord: `com.mysql.jdbc.Driver` for MySQL/MariaDB
|
* BungeeCord: `com.mysql.jdbc.Driver` for MySQL/MariaDB/PostgreSQL
|
||||||
* Velocity: `fastlogin.mariadb.jdbc.Driver` for MySQL/MariaDB
|
* Velocity: `fastlogin.mariadb.jdbc.Driver` for MySQL/MariaDB/PostgreSQL
|
||||||
* Note the embedded file storage SQLite is not available
|
* Note the embedded file storage SQLite is not available
|
||||||
* MySQL/MariaDB requires an external database server running. Check your server provider if there is one available
|
* MySQL/MariaDB/PostgreSQL requires an external database server running. Check your server provider if there is one available
|
||||||
or install one.
|
or install one.
|
||||||
6. Set proxy and Spigot in offline mode by setting the value `onlinemode` in your `config.yml` to false
|
6. Set proxy and Spigot in offline mode by setting the value `onlinemode` in your `config.yml` to false
|
||||||
7. You should *always* configure the firewall for your Spigot server so that it's only accessible through your proxy
|
7. You should *always* configure the firewall for your Spigot server so that it's only accessible through your proxy
|
||||||
|
@ -36,6 +36,7 @@ import com.github.games647.fastlogin.core.antibot.TickingRateLimiter;
|
|||||||
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.PostgreSQLStorage;
|
||||||
import com.github.games647.fastlogin.core.storage.MySQLStorage;
|
import com.github.games647.fastlogin.core.storage.MySQLStorage;
|
||||||
import com.github.games647.fastlogin.core.storage.SQLStorage;
|
import com.github.games647.fastlogin.core.storage.SQLStorage;
|
||||||
import com.github.games647.fastlogin.core.storage.SQLiteStorage;
|
import com.github.games647.fastlogin.core.storage.SQLiteStorage;
|
||||||
@ -230,6 +231,24 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
|
|||||||
|
|
||||||
if (type.contains("sqlite")) {
|
if (type.contains("sqlite")) {
|
||||||
storage = new SQLiteStorage(plugin, database, databaseConfig);
|
storage = new SQLiteStorage(plugin, database, databaseConfig);
|
||||||
|
} else if (type.contains("postgresql")) {
|
||||||
|
String host = config.get("host", "");
|
||||||
|
int port = config.get("port", 3306);
|
||||||
|
boolean useSSL = config.get("useSSL", false);
|
||||||
|
|
||||||
|
if (useSSL) {
|
||||||
|
boolean publicKeyRetrieval = config.getBoolean("allowPublicKeyRetrieval", false);
|
||||||
|
String rsaPublicKeyFile = config.getString("ServerRSAPublicKeyFile");
|
||||||
|
String sslMode = config.getString("sslMode", "Required");
|
||||||
|
|
||||||
|
databaseConfig.addDataSourceProperty("allowPublicKeyRetrieval", publicKeyRetrieval);
|
||||||
|
databaseConfig.addDataSourceProperty("serverRSAPublicKeyFile", rsaPublicKeyFile);
|
||||||
|
databaseConfig.addDataSourceProperty("sslMode", sslMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
databaseConfig.setUsername(config.get("username", ""));
|
||||||
|
databaseConfig.setPassword(config.getString("password"));
|
||||||
|
storage = new PostgreSQLStorage(plugin, type, host, port, database, databaseConfig, useSSL);
|
||||||
} else {
|
} else {
|
||||||
String host = config.get("host", "");
|
String host = config.get("host", "");
|
||||||
int port = config.get("port", 3306);
|
int port = config.get("port", 3306);
|
||||||
|
@ -0,0 +1,101 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015-2023 games647 and contributors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
package com.github.games647.fastlogin.core.storage;
|
||||||
|
|
||||||
|
import com.github.games647.fastlogin.core.shared.PlatformPlugin;
|
||||||
|
import com.zaxxer.hikari.HikariConfig;
|
||||||
|
|
||||||
|
public class PostgreSQLStorage extends SQLStorage {
|
||||||
|
|
||||||
|
private static final String JDBC_PROTOCOL = "jdbc:";
|
||||||
|
|
||||||
|
public PostgreSQLStorage(PlatformPlugin<?> plugin, String driver, String host, int port, String database,
|
||||||
|
HikariConfig config, boolean useSSL) {
|
||||||
|
super(plugin.getLog(), plugin.getName(), plugin.getThreadFactory(),
|
||||||
|
setParams(config, driver, host, port, database, useSSL));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static HikariConfig setParams(HikariConfig config,
|
||||||
|
String driver, String host, int port, String database,
|
||||||
|
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);
|
||||||
|
|
||||||
|
// adding paranoid, hides hostname, username, version and so
|
||||||
|
// could be useful for hiding server details
|
||||||
|
config.addDataSourceProperty("paranoid", true);
|
||||||
|
|
||||||
|
config.setJdbcUrl(JDBC_PROTOCOL + buildJDBCUrl(driver, host, port, database));
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String buildJDBCUrl(String driver, String host, int port, String database) {
|
||||||
|
return "postgresql://" + host + ':' + port + '/' + database;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getCreateTableStmt() {
|
||||||
|
// PostgreSQL has a different syntax for id column
|
||||||
|
return CREATE_TABLE_STMT
|
||||||
|
.replace("`", "\"")
|
||||||
|
.replace("INTEGER PRIMARY KEY AUTO_INCREMENT", "SERIAL PRIMARY KEY");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getAddFloodgateColumnStmt() {
|
||||||
|
// PostgreSQL has a different syntax
|
||||||
|
return ADD_FLOODGATE_COLUMN_STMT
|
||||||
|
.replace("`", "\"")
|
||||||
|
.replace("INTEGER(3)", "INTEGER");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getLoadByNameStmt() {
|
||||||
|
return LOAD_BY_NAME_STMT
|
||||||
|
.replace("`", "\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getLoadByUuidStmt() {
|
||||||
|
return LOAD_BY_UUID_STMT
|
||||||
|
.replace("`", "\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getInsertProfileStmt() {
|
||||||
|
return INSERT_PROFILE_STMT
|
||||||
|
.replace("`", "\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getUpdateProfileStmt() {
|
||||||
|
return UPDATE_PROFILE_STMT
|
||||||
|
.replace("`", "\"");
|
||||||
|
}
|
||||||
|
}
|
@ -61,14 +61,14 @@ public abstract class SQLStorage implements AuthStorage {
|
|||||||
protected static final String ADD_FLOODGATE_COLUMN_STMT = "ALTER TABLE `" + PREMIUM_TABLE
|
protected static final String ADD_FLOODGATE_COLUMN_STMT = "ALTER TABLE `" + PREMIUM_TABLE
|
||||||
+ "` ADD COLUMN `Floodgate` INTEGER(3)";
|
+ "` ADD COLUMN `Floodgate` INTEGER(3)";
|
||||||
|
|
||||||
protected static final String LOAD_BY_NAME = "SELECT * FROM `" + PREMIUM_TABLE
|
protected static final String LOAD_BY_NAME_STMT = "SELECT * FROM `" + PREMIUM_TABLE
|
||||||
+ "` WHERE `Name`=? LIMIT 1";
|
+ "` WHERE `Name`=? LIMIT 1";
|
||||||
protected static final String LOAD_BY_UUID = "SELECT * FROM `" + PREMIUM_TABLE
|
protected static final String LOAD_BY_UUID_STMT = "SELECT * FROM `" + PREMIUM_TABLE
|
||||||
+ "` WHERE `UUID`=? LIMIT 1";
|
+ "` WHERE `UUID`=? LIMIT 1";
|
||||||
protected static final String INSERT_PROFILE = "INSERT INTO `" + PREMIUM_TABLE
|
protected static final String INSERT_PROFILE_STMT = "INSERT INTO `" + PREMIUM_TABLE
|
||||||
+ "` (`UUID`, `Name`, `Premium`, `Floodgate`, `LastIp`) " + "VALUES (?, ?, ?, ?, ?) ";
|
+ "` (`UUID`, `Name`, `Premium`, `Floodgate`, `LastIp`) " + "VALUES (?, ?, ?, ?, ?) ";
|
||||||
// limit not necessary here, because it's unique
|
// limit not necessary here, because it's unique
|
||||||
protected static final String UPDATE_PROFILE = "UPDATE `" + PREMIUM_TABLE
|
protected static final String UPDATE_PROFILE_STMT = "UPDATE `" + PREMIUM_TABLE
|
||||||
+ "` SET `UUID`=?, `Name`=?, `Premium`=?, `Floodgate`=?, `LastIp`=?, "
|
+ "` SET `UUID`=?, `Name`=?, `Premium`=?, `Floodgate`=?, `LastIp`=?, "
|
||||||
+ "`LastLogin`=CURRENT_TIMESTAMP WHERE `UserID`=?";
|
+ "`LastLogin`=CURRENT_TIMESTAMP WHERE `UserID`=?";
|
||||||
|
|
||||||
@ -97,7 +97,7 @@ public abstract class SQLStorage implements AuthStorage {
|
|||||||
// add Floodgate column
|
// add Floodgate column
|
||||||
DatabaseMetaData md = con.getMetaData();
|
DatabaseMetaData md = con.getMetaData();
|
||||||
if (isColumnMissing(md, "Floodgate")) {
|
if (isColumnMissing(md, "Floodgate")) {
|
||||||
stmt.executeUpdate(ADD_FLOODGATE_COLUMN_STMT);
|
stmt.executeUpdate(getAddFloodgateColumnStmt());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -112,7 +112,7 @@ public abstract class SQLStorage implements AuthStorage {
|
|||||||
@Override
|
@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(getLoadByNameStmt())
|
||||||
) {
|
) {
|
||||||
loadStmt.setString(1, name);
|
loadStmt.setString(1, name);
|
||||||
|
|
||||||
@ -130,7 +130,7 @@ public abstract class SQLStorage implements AuthStorage {
|
|||||||
@Override
|
@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(getLoadByUuidStmt())) {
|
||||||
loadStmt.setString(1, UUIDAdapter.toMojangId(uuid));
|
loadStmt.setString(1, UUIDAdapter.toMojangId(uuid));
|
||||||
|
|
||||||
try (ResultSet resultSet = loadStmt.executeQuery()) {
|
try (ResultSet resultSet = loadStmt.executeQuery()) {
|
||||||
@ -177,7 +177,7 @@ public abstract class SQLStorage implements AuthStorage {
|
|||||||
playerProfile.getSaveLock().lock();
|
playerProfile.getSaveLock().lock();
|
||||||
try {
|
try {
|
||||||
if (playerProfile.isSaved()) {
|
if (playerProfile.isSaved()) {
|
||||||
try (PreparedStatement saveStmt = con.prepareStatement(UPDATE_PROFILE)) {
|
try (PreparedStatement saveStmt = con.prepareStatement(getUpdateProfileStmt())) {
|
||||||
saveStmt.setString(1, uuid);
|
saveStmt.setString(1, uuid);
|
||||||
saveStmt.setString(2, playerProfile.getName());
|
saveStmt.setString(2, playerProfile.getName());
|
||||||
saveStmt.setBoolean(3, playerProfile.isPremium());
|
saveStmt.setBoolean(3, playerProfile.isPremium());
|
||||||
@ -188,7 +188,8 @@ public abstract class SQLStorage implements AuthStorage {
|
|||||||
saveStmt.execute();
|
saveStmt.execute();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
try (PreparedStatement saveStmt = con.prepareStatement(INSERT_PROFILE, RETURN_GENERATED_KEYS)) {
|
try (PreparedStatement saveStmt = con.prepareStatement(getInsertProfileStmt(),
|
||||||
|
RETURN_GENERATED_KEYS)) {
|
||||||
saveStmt.setString(1, uuid);
|
saveStmt.setString(1, uuid);
|
||||||
|
|
||||||
saveStmt.setString(2, playerProfile.getName());
|
saveStmt.setString(2, playerProfile.getName());
|
||||||
@ -214,13 +215,37 @@ public abstract class SQLStorage implements AuthStorage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SQLite has a slightly different syntax, so this will be overridden by SQLiteStorage
|
* SQLite and PostgreSQL have a slightly different syntax, so this will be overridden by SQLiteStorage and so on...
|
||||||
* @return An SQL Statement to create the `premium` table
|
* @return An SQL Statement to create the `premium` table
|
||||||
*/
|
*/
|
||||||
protected String getCreateTableStmt() {
|
protected String getCreateTableStmt() {
|
||||||
return CREATE_TABLE_STMT;
|
return CREATE_TABLE_STMT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PostgreSQL has a slightly different syntax, so this will be overridden by PostgreSQLStorage
|
||||||
|
* @return An SQL Statement to create the `premium` table
|
||||||
|
*/
|
||||||
|
protected String getAddFloodgateColumnStmt() {
|
||||||
|
return ADD_FLOODGATE_COLUMN_STMT;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getLoadByNameStmt() {
|
||||||
|
return LOAD_BY_NAME_STMT;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getLoadByUuidStmt() {
|
||||||
|
return LOAD_BY_UUID_STMT;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getInsertProfileStmt() {
|
||||||
|
return INSERT_PROFILE_STMT;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getUpdateProfileStmt() {
|
||||||
|
return UPDATE_PROFILE_STMT;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
dataSource.close();
|
dataSource.close();
|
||||||
|
@ -289,6 +289,15 @@ database: '{pluginDir}/FastLogin.db'
|
|||||||
#username: 'myUser'
|
#username: 'myUser'
|
||||||
#password: 'myPassword'
|
#password: 'myPassword'
|
||||||
|
|
||||||
|
# PostgreSQL
|
||||||
|
# If you want to enable it, uncomment only the lines below; this not this line.
|
||||||
|
#driver: 'postgresql'
|
||||||
|
#host: '127.0.0.1'
|
||||||
|
#port: 5432
|
||||||
|
#database: 'fastlogin'
|
||||||
|
#username: 'myUser'
|
||||||
|
#password: 'myPassword'
|
||||||
|
|
||||||
# Advanced Connection Pool settings in seconds
|
# Advanced Connection Pool settings in seconds
|
||||||
#timeout: 30
|
#timeout: 30
|
||||||
#lifetime: 30
|
#lifetime: 30
|
||||||
|
Reference in New Issue
Block a user