Skip to content

Commit 56e43fb

Browse files
committed
Add support for postgresql
1 parent a65a5f3 commit 56e43fb

File tree

5 files changed

+167
-13
lines changed

5 files changed

+167
-13
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,10 +117,10 @@ Install the plugin on both platforms, that is proxy (BungeeCord or Velocity) and
117117
4. Activate ip forwarding in your proxy config
118118
5. Check your database settings in the config of FastLogin on your proxy
119119
* The proxies only ship with a limited set of drivers where Spigot supports more. Therefore, these are supported:
120-
* BungeeCord: `com.mysql.jdbc.Driver` for MySQL/MariaDB
121-
* Velocity: `fastlogin.mariadb.jdbc.Driver` for MySQL/MariaDB
120+
* BungeeCord: `com.mysql.jdbc.Driver` for MySQL/MariaDB/PostgreSQL
121+
* Velocity: `fastlogin.mariadb.jdbc.Driver` for MySQL/MariaDB/PostgreSQL
122122
* Note the embedded file storage SQLite is not available
123-
* MySQL/MariaDB requires an external database server running. Check your server provider if there is one available
123+
* MySQL/MariaDB/PostgreSQL requires an external database server running. Check your server provider if there is one available
124124
or install one.
125125
6. Set proxy and Spigot in offline mode by setting the value `onlinemode` in your `config.yml` to false
126126
7. You should *always* configure the firewall for your Spigot server so that it's only accessible through your proxy

core/src/main/java/com/github/games647/fastlogin/core/shared/FastLoginCore.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
3737
import com.github.games647.fastlogin.core.hooks.DefaultPasswordGenerator;
3838
import com.github.games647.fastlogin.core.hooks.PasswordGenerator;
39+
import com.github.games647.fastlogin.core.storage.PostgreSQLStorage;
3940
import com.github.games647.fastlogin.core.storage.MySQLStorage;
4041
import com.github.games647.fastlogin.core.storage.SQLStorage;
4142
import com.github.games647.fastlogin.core.storage.SQLiteStorage;
@@ -230,6 +231,24 @@ public boolean setupDatabase() {
230231

231232
if (type.contains("sqlite")) {
232233
storage = new SQLiteStorage(plugin, database, databaseConfig);
234+
} else if (type.contains("postgresql")) {
235+
String host = config.get("host", "");
236+
int port = config.get("port", 3306);
237+
boolean useSSL = config.get("useSSL", false);
238+
239+
if (useSSL) {
240+
boolean publicKeyRetrieval = config.getBoolean("allowPublicKeyRetrieval", false);
241+
String rsaPublicKeyFile = config.getString("ServerRSAPublicKeyFile");
242+
String sslMode = config.getString("sslMode", "Required");
243+
244+
databaseConfig.addDataSourceProperty("allowPublicKeyRetrieval", publicKeyRetrieval);
245+
databaseConfig.addDataSourceProperty("serverRSAPublicKeyFile", rsaPublicKeyFile);
246+
databaseConfig.addDataSourceProperty("sslMode", sslMode);
247+
}
248+
249+
databaseConfig.setUsername(config.get("username", ""));
250+
databaseConfig.setPassword(config.getString("password"));
251+
storage = new PostgreSQLStorage(plugin, type, host, port, database, databaseConfig, useSSL);
233252
} else {
234253
String host = config.get("host", "");
235254
int port = config.get("port", 3306);
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*
2+
* SPDX-License-Identifier: MIT
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2015-2023 games647 and contributors
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in all
16+
* copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24+
* SOFTWARE.
25+
*/
26+
package com.github.games647.fastlogin.core.storage;
27+
28+
import com.github.games647.fastlogin.core.shared.PlatformPlugin;
29+
import com.zaxxer.hikari.HikariConfig;
30+
31+
public class PostgreSQLStorage extends SQLStorage {
32+
33+
private static final String JDBC_PROTOCOL = "jdbc:";
34+
35+
public PostgreSQLStorage(PlatformPlugin<?> plugin, String driver, String host, int port, String database,
36+
HikariConfig config, boolean useSSL) {
37+
super(plugin.getLog(), plugin.getName(), plugin.getThreadFactory(),
38+
setParams(config, driver, host, port, database, useSSL));
39+
}
40+
41+
private static HikariConfig setParams(HikariConfig config,
42+
String driver, String host, int port, String database,
43+
boolean useSSL) {
44+
// Require SSL on the server if requested in config - this will also verify certificate
45+
// Those values are deprecated in favor of sslMode
46+
config.addDataSourceProperty("useSSL", useSSL);
47+
config.addDataSourceProperty("requireSSL", useSSL);
48+
49+
// adding paranoid, hides hostname, username, version and so
50+
// could be useful for hiding server details
51+
config.addDataSourceProperty("paranoid", true);
52+
53+
config.setJdbcUrl(JDBC_PROTOCOL + buildJDBCUrl(driver, host, port, database));
54+
55+
return config;
56+
}
57+
58+
private static String buildJDBCUrl(String driver, String host, int port, String database) {
59+
return "postgresql://" + host + ':' + port + '/' + database;
60+
}
61+
62+
@Override
63+
protected String getCreateTableStmt() {
64+
// PostgreSQL has a different syntax for id column
65+
return CREATE_TABLE_STMT
66+
.replace("`", "\"")
67+
.replace("INTEGER PRIMARY KEY AUTO_INCREMENT", "SERIAL PRIMARY KEY");
68+
}
69+
70+
@Override
71+
protected String getAddFloodgateColumnStmt() {
72+
// PostgreSQL has a different syntax
73+
return ADD_FLOODGATE_COLUMN_STMT
74+
.replace("`", "\"")
75+
.replace("INTEGER(3)", "INTEGER");
76+
}
77+
78+
@Override
79+
protected String getLoadByNameStmt() {
80+
return LOAD_BY_NAME_STMT
81+
.replace("`", "\"");
82+
}
83+
84+
@Override
85+
protected String getLoadByUuidStmt() {
86+
return LOAD_BY_UUID_STMT
87+
.replace("`", "\"");
88+
}
89+
90+
@Override
91+
protected String getInsertProfileStmt() {
92+
return INSERT_PROFILE_STMT
93+
.replace("`", "\"");
94+
}
95+
96+
@Override
97+
protected String getUpdateProfileStmt() {
98+
return UPDATE_PROFILE_STMT
99+
.replace("`", "\"");
100+
}
101+
}

core/src/main/java/com/github/games647/fastlogin/core/storage/SQLStorage.java

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,14 @@ public abstract class SQLStorage implements AuthStorage {
6161
protected static final String ADD_FLOODGATE_COLUMN_STMT = "ALTER TABLE `" + PREMIUM_TABLE
6262
+ "` ADD COLUMN `Floodgate` INTEGER(3)";
6363

64-
protected static final String LOAD_BY_NAME = "SELECT * FROM `" + PREMIUM_TABLE
64+
protected static final String LOAD_BY_NAME_STMT = "SELECT * FROM `" + PREMIUM_TABLE
6565
+ "` WHERE `Name`=? LIMIT 1";
66-
protected static final String LOAD_BY_UUID = "SELECT * FROM `" + PREMIUM_TABLE
66+
protected static final String LOAD_BY_UUID_STMT = "SELECT * FROM `" + PREMIUM_TABLE
6767
+ "` WHERE `UUID`=? LIMIT 1";
68-
protected static final String INSERT_PROFILE = "INSERT INTO `" + PREMIUM_TABLE
68+
protected static final String INSERT_PROFILE_STMT = "INSERT INTO `" + PREMIUM_TABLE
6969
+ "` (`UUID`, `Name`, `Premium`, `Floodgate`, `LastIp`) " + "VALUES (?, ?, ?, ?, ?) ";
7070
// limit not necessary here, because it's unique
71-
protected static final String UPDATE_PROFILE = "UPDATE `" + PREMIUM_TABLE
71+
protected static final String UPDATE_PROFILE_STMT = "UPDATE `" + PREMIUM_TABLE
7272
+ "` SET `UUID`=?, `Name`=?, `Premium`=?, `Floodgate`=?, `LastIp`=?, "
7373
+ "`LastLogin`=CURRENT_TIMESTAMP WHERE `UserID`=?";
7474

@@ -97,7 +97,7 @@ public void createTables() throws SQLException {
9797
// add Floodgate column
9898
DatabaseMetaData md = con.getMetaData();
9999
if (isColumnMissing(md, "Floodgate")) {
100-
stmt.executeUpdate(ADD_FLOODGATE_COLUMN_STMT);
100+
stmt.executeUpdate(getAddFloodgateColumnStmt());
101101
}
102102

103103
}
@@ -112,7 +112,7 @@ private boolean isColumnMissing(DatabaseMetaData metaData, String columnName) th
112112
@Override
113113
public StoredProfile loadProfile(String name) {
114114
try (Connection con = dataSource.getConnection();
115-
PreparedStatement loadStmt = con.prepareStatement(LOAD_BY_NAME)
115+
PreparedStatement loadStmt = con.prepareStatement(getLoadByNameStmt())
116116
) {
117117
loadStmt.setString(1, name);
118118

@@ -130,7 +130,7 @@ public StoredProfile loadProfile(String name) {
130130
@Override
131131
public StoredProfile loadProfile(UUID uuid) {
132132
try (Connection con = dataSource.getConnection();
133-
PreparedStatement loadStmt = con.prepareStatement(LOAD_BY_UUID)) {
133+
PreparedStatement loadStmt = con.prepareStatement(getLoadByUuidStmt())) {
134134
loadStmt.setString(1, UUIDAdapter.toMojangId(uuid));
135135

136136
try (ResultSet resultSet = loadStmt.executeQuery()) {
@@ -177,7 +177,7 @@ public void save(StoredProfile playerProfile) {
177177
playerProfile.getSaveLock().lock();
178178
try {
179179
if (playerProfile.isSaved()) {
180-
try (PreparedStatement saveStmt = con.prepareStatement(UPDATE_PROFILE)) {
180+
try (PreparedStatement saveStmt = con.prepareStatement(getUpdateProfileStmt())) {
181181
saveStmt.setString(1, uuid);
182182
saveStmt.setString(2, playerProfile.getName());
183183
saveStmt.setBoolean(3, playerProfile.isPremium());
@@ -188,7 +188,8 @@ public void save(StoredProfile playerProfile) {
188188
saveStmt.execute();
189189
}
190190
} else {
191-
try (PreparedStatement saveStmt = con.prepareStatement(INSERT_PROFILE, RETURN_GENERATED_KEYS)) {
191+
try (PreparedStatement saveStmt = con.prepareStatement(getInsertProfileStmt(),
192+
RETURN_GENERATED_KEYS)) {
192193
saveStmt.setString(1, uuid);
193194

194195
saveStmt.setString(2, playerProfile.getName());
@@ -214,13 +215,37 @@ public void save(StoredProfile playerProfile) {
214215
}
215216

216217
/**
217-
* SQLite has a slightly different syntax, so this will be overridden by SQLiteStorage
218+
* SQLite and PostgreSQL have a slightly different syntax, so this will be overridden by SQLiteStorage and so on...
218219
* @return An SQL Statement to create the `premium` table
219220
*/
220221
protected String getCreateTableStmt() {
221222
return CREATE_TABLE_STMT;
222223
}
223224

225+
/**
226+
* PostgreSQL has a slightly different syntax, so this will be overridden by PostgreSQLStorage
227+
* @return An SQL Statement to create the `premium` table
228+
*/
229+
protected String getAddFloodgateColumnStmt() {
230+
return ADD_FLOODGATE_COLUMN_STMT;
231+
}
232+
233+
protected String getLoadByNameStmt() {
234+
return LOAD_BY_NAME_STMT;
235+
}
236+
237+
protected String getLoadByUuidStmt() {
238+
return LOAD_BY_UUID_STMT;
239+
}
240+
241+
protected String getInsertProfileStmt() {
242+
return INSERT_PROFILE_STMT;
243+
}
244+
245+
protected String getUpdateProfileStmt() {
246+
return UPDATE_PROFILE_STMT;
247+
}
248+
224249
@Override
225250
public void close() {
226251
dataSource.close();

core/src/main/resources/config.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,15 @@ database: '{pluginDir}/FastLogin.db'
289289
#username: 'myUser'
290290
#password: 'myPassword'
291291

292+
# PostgreSQL
293+
# If you want to enable it, uncomment only the lines below; this not this line.
294+
#driver: 'postgresql'
295+
#host: '127.0.0.1'
296+
#port: 5432
297+
#database: 'fastlogin'
298+
#username: 'myUser'
299+
#password: 'myPassword'
300+
292301
# Advanced Connection Pool settings in seconds
293302
#timeout: 30
294303
#lifetime: 30

0 commit comments

Comments
 (0)