mirror of
https://github.com/GravitLauncher/Launcher
synced 2024-12-23 00:51:01 +03:00
Merge pull request #621 from AlexCatze/feature-sqlabstraction
[FEATURE] Move shared SQL code to abstract class
This commit is contained in:
commit
1996525b65
6 changed files with 349 additions and 537 deletions
|
@ -11,7 +11,7 @@
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
|
||||||
public final class MySQLSourceConfig implements AutoCloseable {
|
public final class MySQLSourceConfig implements AutoCloseable, SQLSourceConfig {
|
||||||
|
|
||||||
public static final int TIMEOUT = VerifyHelper.verifyInt(
|
public static final int TIMEOUT = VerifyHelper.verifyInt(
|
||||||
Integer.parseUnsignedInt(System.getProperty("launcher.mysql.idleTimeout", Integer.toString(5000))),
|
Integer.parseUnsignedInt(System.getProperty("launcher.mysql.idleTimeout", Integer.toString(5000))),
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
|
||||||
public final class PostgreSQLSourceConfig implements AutoCloseable {
|
public final class PostgreSQLSourceConfig implements AutoCloseable, SQLSourceConfig {
|
||||||
public static final int TIMEOUT = VerifyHelper.verifyInt(
|
public static final int TIMEOUT = VerifyHelper.verifyInt(
|
||||||
Integer.parseUnsignedInt(System.getProperty("launcher.postgresql.idleTimeout", Integer.toString(5000))),
|
Integer.parseUnsignedInt(System.getProperty("launcher.postgresql.idleTimeout", Integer.toString(5000))),
|
||||||
VerifyHelper.POSITIVE, "launcher.postgresql.idleTimeout can't be <= 5000");
|
VerifyHelper.POSITIVE, "launcher.postgresql.idleTimeout can't be <= 5000");
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
package pro.gravit.launchserver.auth;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
public interface SQLSourceConfig {
|
||||||
|
Connection getConnection() throws SQLException;
|
||||||
|
void close();
|
||||||
|
}
|
|
@ -0,0 +1,324 @@
|
||||||
|
package pro.gravit.launchserver.auth.core;
|
||||||
|
|
||||||
|
import io.jsonwebtoken.ExpiredJwtException;
|
||||||
|
import io.jsonwebtoken.JwtException;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import pro.gravit.launcher.ClientPermissions;
|
||||||
|
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||||
|
import pro.gravit.launcher.request.auth.password.AuthPlainPassword;
|
||||||
|
import pro.gravit.launchserver.LaunchServer;
|
||||||
|
import pro.gravit.launchserver.auth.AuthException;
|
||||||
|
import pro.gravit.launchserver.auth.MySQLSourceConfig;
|
||||||
|
import pro.gravit.launchserver.auth.SQLSourceConfig;
|
||||||
|
import pro.gravit.launchserver.auth.password.PasswordVerifier;
|
||||||
|
import pro.gravit.launchserver.helper.LegacySessionHelper;
|
||||||
|
import pro.gravit.launchserver.manangers.AuthManager;
|
||||||
|
import pro.gravit.launchserver.socket.response.auth.AuthResponse;
|
||||||
|
import pro.gravit.utils.helper.SecurityHelper;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.sql.*;
|
||||||
|
import java.time.Clock;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public abstract class AbstractSQLCoreProvider extends AuthCoreProvider {
|
||||||
|
public transient Logger logger = LogManager.getLogger();
|
||||||
|
|
||||||
|
public abstract SQLSourceConfig getSQLConfig();
|
||||||
|
|
||||||
|
public int expireSeconds = 3600;
|
||||||
|
public String uuidColumn;
|
||||||
|
public String usernameColumn;
|
||||||
|
public String accessTokenColumn;
|
||||||
|
public String passwordColumn;
|
||||||
|
public String serverIDColumn;
|
||||||
|
public String table;
|
||||||
|
|
||||||
|
public String permissionsTable;
|
||||||
|
public String permissionsPermissionColumn;
|
||||||
|
public String permissionsUUIDColumn;
|
||||||
|
|
||||||
|
public PasswordVerifier passwordVerifier;
|
||||||
|
public String customQueryByUUIDSQL;
|
||||||
|
public String customQueryByUsernameSQL;
|
||||||
|
public String customQueryByLoginSQL;
|
||||||
|
public String customQueryPermissionsByUUIDSQL;
|
||||||
|
public String customUpdateAuthSQL;
|
||||||
|
public String customUpdateServerIdSQL;
|
||||||
|
// Prepared SQL queries
|
||||||
|
public transient String queryByUUIDSQL;
|
||||||
|
public transient String queryByUsernameSQL;
|
||||||
|
public transient String queryByLoginSQL;
|
||||||
|
public transient String queryPermissionsByUUIDSQL;
|
||||||
|
public transient String updateAuthSQL;
|
||||||
|
public transient String updateServerIDSQL;
|
||||||
|
|
||||||
|
public transient LaunchServer server;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public User getUserByUsername(String username) {
|
||||||
|
try {
|
||||||
|
return query(queryByUsernameSQL, username);
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.error("SQL error", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public User getUserByUUID(UUID uuid) {
|
||||||
|
try {
|
||||||
|
return query(queryByUUIDSQL, uuid.toString());
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.error("SQL error", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public User getUserByLogin(String login) {
|
||||||
|
try {
|
||||||
|
return query(queryByLoginSQL, login);
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.error("SQL error", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UserSession getUserSessionByOAuthAccessToken(String accessToken) throws OAuthAccessTokenExpired {
|
||||||
|
try {
|
||||||
|
var info = LegacySessionHelper.getJwtInfoFromAccessToken(accessToken, server.keyAgreementManager.ecdsaPublicKey);
|
||||||
|
var user = (SQLUser) getUserByUUID(info.uuid());
|
||||||
|
if(user == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new SQLUserSession(user);
|
||||||
|
} catch (ExpiredJwtException e) {
|
||||||
|
throw new OAuthAccessTokenExpired();
|
||||||
|
} catch (JwtException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthManager.AuthReport refreshAccessToken(String refreshToken, AuthResponse.AuthContext context) {
|
||||||
|
String[] parts = refreshToken.split("\\.");
|
||||||
|
if(parts.length != 2) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String username = parts[0];
|
||||||
|
String token = parts[1];
|
||||||
|
var user = (SQLUser) getUserByUsername(username);
|
||||||
|
if(user == null || user.password == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
var realToken = LegacySessionHelper.makeRefreshTokenFromPassword(username, user.password, server.keyAgreementManager.legacySalt);
|
||||||
|
if(!token.equals(realToken)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
var accessToken = LegacySessionHelper.makeAccessJwtTokenFromString(user, LocalDateTime.now(Clock.systemUTC()).plusSeconds(expireSeconds), server.keyAgreementManager.ecdsaPrivateKey);
|
||||||
|
return new AuthManager.AuthReport(null, accessToken, refreshToken, expireSeconds * 1000L, new SQLUserSession(user));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthManager.AuthReport authorize(String login, AuthResponse.AuthContext context, AuthRequest.AuthPasswordInterface password, boolean minecraftAccess) throws IOException {
|
||||||
|
SQLUser SQLUser = (SQLUser) getUserByLogin(login);
|
||||||
|
if(SQLUser == null) {
|
||||||
|
throw AuthException.wrongPassword();
|
||||||
|
}
|
||||||
|
if(context != null) {
|
||||||
|
AuthPlainPassword plainPassword = (AuthPlainPassword) password;
|
||||||
|
if(plainPassword == null) {
|
||||||
|
throw AuthException.wrongPassword();
|
||||||
|
}
|
||||||
|
if(!passwordVerifier.check(SQLUser.password, plainPassword.password)) {
|
||||||
|
throw AuthException.wrongPassword();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SQLUserSession session = new SQLUserSession(SQLUser);
|
||||||
|
var accessToken = LegacySessionHelper.makeAccessJwtTokenFromString(SQLUser, LocalDateTime.now(Clock.systemUTC()).plusSeconds(expireSeconds), server.keyAgreementManager.ecdsaPrivateKey);
|
||||||
|
var refreshToken = SQLUser.username.concat(".").concat(LegacySessionHelper.makeRefreshTokenFromPassword(SQLUser.username, SQLUser.password, server.keyAgreementManager.legacySalt));
|
||||||
|
if (minecraftAccess) {
|
||||||
|
String minecraftAccessToken = SecurityHelper.randomStringToken();
|
||||||
|
updateAuth(SQLUser, minecraftAccessToken);
|
||||||
|
return AuthManager.AuthReport.ofOAuthWithMinecraft(minecraftAccessToken, accessToken, refreshToken, expireSeconds * 1000L, session);
|
||||||
|
} else {
|
||||||
|
return AuthManager.AuthReport.ofOAuth(accessToken, refreshToken, expireSeconds * 1000L, session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(LaunchServer server) {
|
||||||
|
this.server = server;
|
||||||
|
if (getSQLConfig() == null) logger.error("SQLHolder cannot be null");
|
||||||
|
if (uuidColumn == null) logger.error("uuidColumn cannot be null");
|
||||||
|
if (usernameColumn == null) logger.error("usernameColumn cannot be null");
|
||||||
|
if (accessTokenColumn == null) logger.error("accessTokenColumn cannot be null");
|
||||||
|
if (serverIDColumn == null) logger.error("serverIDColumn cannot be null");
|
||||||
|
if (table == null) logger.error("table cannot be null");
|
||||||
|
// Prepare SQL queries
|
||||||
|
String userInfoCols = String.format("%s, %s, %s, %s, %s", uuidColumn, usernameColumn, accessTokenColumn, serverIDColumn, passwordColumn);
|
||||||
|
queryByUUIDSQL = customQueryByUUIDSQL != null ? customQueryByUUIDSQL : String.format("SELECT %s FROM %s WHERE %s=? LIMIT 1", userInfoCols,
|
||||||
|
table, uuidColumn);
|
||||||
|
queryByUsernameSQL = customQueryByUsernameSQL != null ? customQueryByUsernameSQL : String.format("SELECT %s FROM %s WHERE %s=? LIMIT 1",
|
||||||
|
userInfoCols, table, usernameColumn);
|
||||||
|
queryByLoginSQL = customQueryByLoginSQL != null ? customQueryByLoginSQL : queryByUsernameSQL;
|
||||||
|
|
||||||
|
queryPermissionsByUUIDSQL = customQueryPermissionsByUUIDSQL != null ? customQueryPermissionsByUUIDSQL : String.format("SELECT (%s) FROM %s WHERE %s=?",
|
||||||
|
permissionsPermissionColumn, permissionsTable, permissionsUUIDColumn);
|
||||||
|
|
||||||
|
updateAuthSQL = customUpdateAuthSQL != null ? customUpdateAuthSQL : String.format("UPDATE %s SET %s=?, %s=NULL WHERE %s=?",
|
||||||
|
table, accessTokenColumn, serverIDColumn, uuidColumn);
|
||||||
|
updateServerIDSQL = customUpdateServerIdSQL != null ? customUpdateServerIdSQL : String.format("UPDATE %s SET %s=? WHERE %s=?",
|
||||||
|
table, serverIDColumn, uuidColumn);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean updateAuth(User user, String accessToken) throws IOException {
|
||||||
|
try (Connection c = getSQLConfig().getConnection()) {
|
||||||
|
SQLUser SQLUser = (SQLUser) user;
|
||||||
|
SQLUser.accessToken = accessToken;
|
||||||
|
PreparedStatement s = c.prepareStatement(updateAuthSQL);
|
||||||
|
s.setString(1, accessToken);
|
||||||
|
s.setString(2, user.getUUID().toString());
|
||||||
|
s.setQueryTimeout(MySQLSourceConfig.TIMEOUT);
|
||||||
|
return s.executeUpdate() > 0;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new IOException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean updateServerID(User user, String serverID) throws IOException {
|
||||||
|
try (Connection c = getSQLConfig().getConnection()) {
|
||||||
|
SQLUser SQLUser = (SQLUser) user;
|
||||||
|
SQLUser.serverId = serverID;
|
||||||
|
PreparedStatement s = c.prepareStatement(updateServerIDSQL);
|
||||||
|
s.setString(1, serverID);
|
||||||
|
s.setString(2, user.getUUID().toString());
|
||||||
|
s.setQueryTimeout(MySQLSourceConfig.TIMEOUT);
|
||||||
|
return s.executeUpdate() > 0;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new IOException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
getSQLConfig().close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private SQLUser constructUser(ResultSet set) throws SQLException {
|
||||||
|
return set.next() ? new SQLUser(UUID.fromString(set.getString(uuidColumn)), set.getString(usernameColumn),
|
||||||
|
set.getString(accessTokenColumn), set.getString(serverIDColumn), set.getString(passwordColumn), requestPermissions(set.getString(uuidColumn))) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClientPermissions requestPermissions (String uuid) throws SQLException
|
||||||
|
{
|
||||||
|
try (Connection c = getSQLConfig().getConnection()) {
|
||||||
|
PreparedStatement s = c.prepareStatement(queryPermissionsByUUIDSQL);
|
||||||
|
s.setString(1, uuid);
|
||||||
|
s.setQueryTimeout(MySQLSourceConfig.TIMEOUT);
|
||||||
|
ResultSet set = s.executeQuery();
|
||||||
|
ClientPermissions perms = new ClientPermissions();
|
||||||
|
while (set.next()) {
|
||||||
|
perms.addPerm(set.getString(permissionsPermissionColumn));
|
||||||
|
}
|
||||||
|
return perms;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new SQLException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private User query(String sql, String value) throws IOException {
|
||||||
|
try (Connection c = getSQLConfig().getConnection()) {
|
||||||
|
PreparedStatement s = c.prepareStatement(sql);
|
||||||
|
s.setString(1, value);
|
||||||
|
s.setQueryTimeout(MySQLSourceConfig.TIMEOUT);
|
||||||
|
try (ResultSet set = s.executeQuery()) {
|
||||||
|
return constructUser(set);
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new IOException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class SQLUser implements User {
|
||||||
|
protected UUID uuid;
|
||||||
|
protected String username;
|
||||||
|
protected String accessToken;
|
||||||
|
protected String serverId;
|
||||||
|
protected String password;
|
||||||
|
protected ClientPermissions permissions;
|
||||||
|
|
||||||
|
public SQLUser(UUID uuid, String username, String accessToken, String serverId, String password, ClientPermissions permissions) {
|
||||||
|
this.uuid = uuid;
|
||||||
|
this.username = username;
|
||||||
|
this.accessToken = accessToken;
|
||||||
|
this.serverId = serverId;
|
||||||
|
this.password = password;
|
||||||
|
this.permissions = permissions;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UUID getUUID() {
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getServerId() {
|
||||||
|
return serverId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAccessToken() {
|
||||||
|
return accessToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClientPermissions getPermissions() {
|
||||||
|
return permissions;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "SQLUser{" +
|
||||||
|
"uuid=" + uuid +
|
||||||
|
", username='" + username + '\'' +
|
||||||
|
", permissions=" + permissions +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class SQLUserSession implements UserSession {
|
||||||
|
private final SQLUser user;
|
||||||
|
private final String id;
|
||||||
|
|
||||||
|
public SQLUserSession(SQLUser user) {
|
||||||
|
this.user = user;
|
||||||
|
this.id = user.username;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getID() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public User getUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getExpireIn() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,6 +11,7 @@
|
||||||
import pro.gravit.launchserver.LaunchServer;
|
import pro.gravit.launchserver.LaunchServer;
|
||||||
import pro.gravit.launchserver.auth.AuthException;
|
import pro.gravit.launchserver.auth.AuthException;
|
||||||
import pro.gravit.launchserver.auth.MySQLSourceConfig;
|
import pro.gravit.launchserver.auth.MySQLSourceConfig;
|
||||||
|
import pro.gravit.launchserver.auth.SQLSourceConfig;
|
||||||
import pro.gravit.launchserver.auth.core.interfaces.UserHardware;
|
import pro.gravit.launchserver.auth.core.interfaces.UserHardware;
|
||||||
import pro.gravit.launchserver.auth.core.interfaces.provider.AuthSupportHardware;
|
import pro.gravit.launchserver.auth.core.interfaces.provider.AuthSupportHardware;
|
||||||
import pro.gravit.launchserver.auth.core.interfaces.user.UserSupportHardware;
|
import pro.gravit.launchserver.auth.core.interfaces.user.UserSupportHardware;
|
||||||
|
@ -32,28 +33,13 @@
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public class MySQLCoreProvider extends AuthCoreProvider implements AuthSupportHardware {
|
public class MySQLCoreProvider extends AbstractSQLCoreProvider implements AuthSupportHardware {
|
||||||
private transient final Logger logger = LogManager.getLogger();
|
|
||||||
public MySQLSourceConfig mySQLHolder;
|
public MySQLSourceConfig mySQLHolder;
|
||||||
|
|
||||||
public int expireSeconds = 3600;
|
|
||||||
public String uuidColumn;
|
|
||||||
public String usernameColumn;
|
|
||||||
public String accessTokenColumn;
|
|
||||||
public String passwordColumn;
|
|
||||||
public String serverIDColumn;
|
|
||||||
public String hardwareIdColumn;
|
public String hardwareIdColumn;
|
||||||
public String table;
|
|
||||||
|
|
||||||
public String tableHWID = "hwids";
|
public String tableHWID = "hwids";
|
||||||
public String tableHWIDLog = "hwidLog";
|
public String tableHWIDLog = "hwidLog";
|
||||||
public PasswordVerifier passwordVerifier;
|
|
||||||
public double criticalCompareLevel = 1.0;
|
public double criticalCompareLevel = 1.0;
|
||||||
public String customQueryByUUIDSQL;
|
|
||||||
public String customQueryByUsernameSQL;
|
|
||||||
public String customQueryByLoginSQL;
|
|
||||||
public String customUpdateAuthSQL;
|
|
||||||
public String customUpdateServerIdSQL;
|
|
||||||
private transient String sqlFindHardwareByPublicKey;
|
private transient String sqlFindHardwareByPublicKey;
|
||||||
private transient String sqlFindHardwareByData;
|
private transient String sqlFindHardwareByData;
|
||||||
private transient String sqlFindHardwareById;
|
private transient String sqlFindHardwareById;
|
||||||
|
@ -63,130 +49,16 @@ public class MySQLCoreProvider extends AuthCoreProvider implements AuthSupportHa
|
||||||
private transient String sqlUpdateHardwareBanned;
|
private transient String sqlUpdateHardwareBanned;
|
||||||
private transient String sqlUpdateUsers;
|
private transient String sqlUpdateUsers;
|
||||||
private transient String sqlUsersByHwidId;
|
private transient String sqlUsersByHwidId;
|
||||||
// Prepared SQL queries
|
|
||||||
private transient String queryByUUIDSQL;
|
|
||||||
private transient String queryByUsernameSQL;
|
|
||||||
private transient String queryByLoginSQL;
|
|
||||||
private transient String updateAuthSQL;
|
|
||||||
private transient String updateServerIDSQL;
|
|
||||||
|
|
||||||
private transient LaunchServer server;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public User getUserByUsername(String username) {
|
public SQLSourceConfig getSQLConfig() {
|
||||||
try {
|
return mySQLHolder;
|
||||||
return query(queryByUsernameSQL, username);
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.error("SQL error", e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public User getUserByUUID(UUID uuid) {
|
|
||||||
try {
|
|
||||||
return query(queryByUUIDSQL, uuid.toString());
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.error("SQL error", e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public User getUserByLogin(String login) {
|
|
||||||
try {
|
|
||||||
return query(queryByLoginSQL, login);
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.error("SQL error", e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public UserSession getUserSessionByOAuthAccessToken(String accessToken) throws OAuthAccessTokenExpired {
|
|
||||||
try {
|
|
||||||
var info = LegacySessionHelper.getJwtInfoFromAccessToken(accessToken, server.keyAgreementManager.ecdsaPublicKey);
|
|
||||||
var user = (MySQLUser) getUserByUUID(info.uuid());
|
|
||||||
if(user == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return new MySQLUserSession(user);
|
|
||||||
} catch (ExpiredJwtException e) {
|
|
||||||
throw new OAuthAccessTokenExpired();
|
|
||||||
} catch (JwtException e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AuthManager.AuthReport refreshAccessToken(String refreshToken, AuthResponse.AuthContext context) {
|
|
||||||
String[] parts = refreshToken.split("\\.");
|
|
||||||
if(parts.length != 2) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
String username = parts[0];
|
|
||||||
String token = parts[1];
|
|
||||||
var user = (MySQLUser) getUserByUsername(username);
|
|
||||||
if(user == null || user.password == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
var realToken = LegacySessionHelper.makeRefreshTokenFromPassword(username, user.password, server.keyAgreementManager.legacySalt);
|
|
||||||
if(!token.equals(realToken)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
var accessToken = LegacySessionHelper.makeAccessJwtTokenFromString(user, LocalDateTime.now(Clock.systemUTC()).plusSeconds(expireSeconds), server.keyAgreementManager.ecdsaPrivateKey);
|
|
||||||
return new AuthManager.AuthReport(null, accessToken, refreshToken, expireSeconds * 1000L, new MySQLUserSession(user));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AuthManager.AuthReport authorize(String login, AuthResponse.AuthContext context, AuthRequest.AuthPasswordInterface password, boolean minecraftAccess) throws IOException {
|
|
||||||
MySQLUser mySQLUser = (MySQLUser) getUserByLogin(login);
|
|
||||||
if(mySQLUser == null) {
|
|
||||||
throw AuthException.wrongPassword();
|
|
||||||
}
|
|
||||||
if(context != null) {
|
|
||||||
AuthPlainPassword plainPassword = (AuthPlainPassword) password;
|
|
||||||
if(plainPassword == null) {
|
|
||||||
throw AuthException.wrongPassword();
|
|
||||||
}
|
|
||||||
if(!passwordVerifier.check(mySQLUser.password, plainPassword.password)) {
|
|
||||||
throw AuthException.wrongPassword();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MySQLUserSession session = new MySQLUserSession(mySQLUser);
|
|
||||||
var accessToken = LegacySessionHelper.makeAccessJwtTokenFromString(mySQLUser, LocalDateTime.now(Clock.systemUTC()).plusSeconds(expireSeconds), server.keyAgreementManager.ecdsaPrivateKey);
|
|
||||||
var refreshToken = mySQLUser.username.concat(".").concat(LegacySessionHelper.makeRefreshTokenFromPassword(mySQLUser.username, mySQLUser.password, server.keyAgreementManager.legacySalt));
|
|
||||||
if (minecraftAccess) {
|
|
||||||
String minecraftAccessToken = SecurityHelper.randomStringToken();
|
|
||||||
updateAuth(mySQLUser, minecraftAccessToken);
|
|
||||||
return AuthManager.AuthReport.ofOAuthWithMinecraft(minecraftAccessToken, accessToken, refreshToken, expireSeconds * 1000L, session);
|
|
||||||
} else {
|
|
||||||
return AuthManager.AuthReport.ofOAuth(accessToken, refreshToken, expireSeconds * 1000L, session);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(LaunchServer server) {
|
public void init(LaunchServer server) {
|
||||||
this.server = server;
|
super.init(server);
|
||||||
if (mySQLHolder == null) logger.error("mySQLHolder cannot be null");
|
|
||||||
if (uuidColumn == null) logger.error("uuidColumn cannot be null");
|
|
||||||
if (usernameColumn == null) logger.error("usernameColumn cannot be null");
|
|
||||||
if (accessTokenColumn == null) logger.error("accessTokenColumn cannot be null");
|
|
||||||
if (serverIDColumn == null) logger.error("serverIDColumn cannot be null");
|
|
||||||
if (hardwareIdColumn == null) logger.error("hardwareIdColumn cannot be null");
|
|
||||||
if (table == null) logger.error("table cannot be null");
|
|
||||||
// Prepare SQL queries
|
|
||||||
String userInfoCols = String.format("%s, %s, %s, %s, %s, %s", uuidColumn, usernameColumn, accessTokenColumn, serverIDColumn, passwordColumn, hardwareIdColumn);
|
String userInfoCols = String.format("%s, %s, %s, %s, %s, %s", uuidColumn, usernameColumn, accessTokenColumn, serverIDColumn, passwordColumn, hardwareIdColumn);
|
||||||
queryByUUIDSQL = customQueryByUUIDSQL != null ? customQueryByUUIDSQL : String.format("SELECT %s FROM %s WHERE %s=? LIMIT 1", userInfoCols,
|
|
||||||
table, uuidColumn);
|
|
||||||
queryByUsernameSQL = customQueryByUsernameSQL != null ? customQueryByUsernameSQL : String.format("SELECT %s FROM %s WHERE %s=? LIMIT 1",
|
|
||||||
userInfoCols, table, usernameColumn);
|
|
||||||
queryByLoginSQL = customQueryByLoginSQL != null ? customQueryByLoginSQL : queryByUsernameSQL;
|
|
||||||
|
|
||||||
updateAuthSQL = customUpdateAuthSQL != null ? customUpdateAuthSQL : String.format("UPDATE %s SET %s=?, %s=NULL WHERE %s=?",
|
|
||||||
table, accessTokenColumn, serverIDColumn, uuidColumn);
|
|
||||||
updateServerIDSQL = customUpdateServerIdSQL != null ? customUpdateServerIdSQL : String.format("UPDATE %s SET %s=? WHERE %s=?",
|
|
||||||
table, serverIDColumn, uuidColumn);
|
|
||||||
String hardwareInfoCols = "id, hwDiskId, baseboardSerialNumber, displayId, bitness, totalMemory, logicalProcessors, physicalProcessors, processorMaxFreq, battery, id, graphicCard, banned, publicKey";
|
String hardwareInfoCols = "id, hwDiskId, baseboardSerialNumber, displayId, bitness, totalMemory, logicalProcessors, physicalProcessors, processorMaxFreq, battery, id, graphicCard, banned, publicKey";
|
||||||
if (sqlFindHardwareByPublicKey == null)
|
if (sqlFindHardwareByPublicKey == null)
|
||||||
sqlFindHardwareByPublicKey = String.format("SELECT %s FROM %s WHERE `publicKey` = ?", hardwareInfoCols, tableHWID);
|
sqlFindHardwareByPublicKey = String.format("SELECT %s FROM %s WHERE `publicKey` = ?", hardwareInfoCols, tableHWID);
|
||||||
|
@ -206,43 +78,9 @@ public void init(LaunchServer server) {
|
||||||
sqlUpdateUsers = String.format("UPDATE %s SET `%s` = ? WHERE `%s` = ?", table, hardwareIdColumn, uuidColumn);
|
sqlUpdateUsers = String.format("UPDATE %s SET `%s` = ? WHERE `%s` = ?", table, hardwareIdColumn, uuidColumn);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean updateAuth(User user, String accessToken) throws IOException {
|
|
||||||
try (Connection c = mySQLHolder.getConnection()) {
|
|
||||||
MySQLUser mySQLUser = (MySQLUser) user;
|
|
||||||
mySQLUser.accessToken = accessToken;
|
|
||||||
PreparedStatement s = c.prepareStatement(updateAuthSQL);
|
|
||||||
s.setString(1, accessToken);
|
|
||||||
s.setString(2, user.getUUID().toString());
|
|
||||||
s.setQueryTimeout(MySQLSourceConfig.TIMEOUT);
|
|
||||||
return s.executeUpdate() > 0;
|
|
||||||
} catch (SQLException e) {
|
|
||||||
throw new IOException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean updateServerID(User user, String serverID) throws IOException {
|
|
||||||
try (Connection c = mySQLHolder.getConnection()) {
|
|
||||||
MySQLUser mySQLUser = (MySQLUser) user;
|
|
||||||
mySQLUser.serverId = serverID;
|
|
||||||
PreparedStatement s = c.prepareStatement(updateServerIDSQL);
|
|
||||||
s.setString(1, serverID);
|
|
||||||
s.setString(2, user.getUUID().toString());
|
|
||||||
s.setQueryTimeout(MySQLSourceConfig.TIMEOUT);
|
|
||||||
return s.executeUpdate() > 0;
|
|
||||||
} catch (SQLException e) {
|
|
||||||
throw new IOException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() throws IOException {
|
|
||||||
mySQLHolder.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
private MySQLUser constructUser(ResultSet set) throws SQLException {
|
private MySQLUser constructUser(ResultSet set) throws SQLException {
|
||||||
return set.next() ? new MySQLUser(UUID.fromString(set.getString(uuidColumn)), set.getString(usernameColumn),
|
return set.next() ? new MySQLUser(UUID.fromString(set.getString(uuidColumn)), set.getString(usernameColumn),
|
||||||
set.getString(accessTokenColumn), set.getString(serverIDColumn), set.getString(passwordColumn), new ClientPermissions(), set.getLong(hardwareIdColumn)) : null;
|
set.getString(accessTokenColumn), set.getString(serverIDColumn), set.getString(passwordColumn), requestPermissions(set.getString(uuidColumn)), set.getLong(hardwareIdColumn)) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private MySQLUserHardware fetchHardwareInfo(ResultSet set) throws SQLException, IOException {
|
private MySQLUserHardware fetchHardwareInfo(ResultSet set) throws SQLException, IOException {
|
||||||
|
@ -270,20 +108,6 @@ private void setUserHardwareId(Connection connection, UUID uuid, long hwidId) th
|
||||||
s.setString(2, uuid.toString());
|
s.setString(2, uuid.toString());
|
||||||
s.executeUpdate();
|
s.executeUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
private User query(String sql, String value) throws IOException {
|
|
||||||
try (Connection c = mySQLHolder.getConnection()) {
|
|
||||||
PreparedStatement s = c.prepareStatement(sql);
|
|
||||||
s.setString(1, value);
|
|
||||||
s.setQueryTimeout(MySQLSourceConfig.TIMEOUT);
|
|
||||||
try (ResultSet set = s.executeQuery()) {
|
|
||||||
return constructUser(set);
|
|
||||||
}
|
|
||||||
} catch (SQLException e) {
|
|
||||||
throw new IOException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UserHardware getHardwareInfoByPublicKey(byte[] publicKey) {
|
public UserHardware getHardwareInfoByPublicKey(byte[] publicKey) {
|
||||||
try (Connection connection = mySQLHolder.getConnection()) {
|
try (Connection connection = mySQLHolder.getConnection()) {
|
||||||
|
@ -371,8 +195,8 @@ public UserHardware createHardwareInfo(HardwareReportRequest.HardwareInfo hardwa
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void connectUserAndHardware(UserSession userSession, UserHardware hardware) {
|
public void connectUserAndHardware(UserSession userSession, UserHardware hardware) {
|
||||||
MySQLUserSession mySQLUserSession = (MySQLUserSession) userSession;
|
SQLUserSession mySQLUserSession = (SQLUserSession) userSession;
|
||||||
MySQLUser mySQLUser = mySQLUserSession.user;
|
MySQLUser mySQLUser = (MySQLUser) mySQLUserSession.getUser();
|
||||||
MySQLUserHardware mySQLUserHardware = (MySQLUserHardware) hardware;
|
MySQLUserHardware mySQLUserHardware = (MySQLUserHardware) hardware;
|
||||||
if (mySQLUser.hwidId == mySQLUserHardware.id) return;
|
if (mySQLUser.hwidId == mySQLUserHardware.id) return;
|
||||||
mySQLUser.hwidId = mySQLUserHardware.id;
|
mySQLUser.hwidId = mySQLUserHardware.id;
|
||||||
|
@ -488,51 +312,14 @@ public String toString() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class MySQLUser implements User, UserSupportHardware {
|
public class MySQLUser extends SQLUser implements UserSupportHardware {
|
||||||
protected UUID uuid;
|
|
||||||
protected String username;
|
|
||||||
protected String accessToken;
|
|
||||||
protected String serverId;
|
|
||||||
protected String password;
|
|
||||||
protected ClientPermissions permissions;
|
|
||||||
protected long hwidId;
|
protected long hwidId;
|
||||||
protected transient MySQLUserHardware hardware;
|
protected transient MySQLUserHardware hardware;
|
||||||
|
|
||||||
public MySQLUser(UUID uuid, String username, String accessToken, String serverId, String password, ClientPermissions permissions, long hwidId) {
|
public MySQLUser(UUID uuid, String username, String accessToken, String serverId, String password, ClientPermissions permissions, long hwidId) {
|
||||||
this.uuid = uuid;
|
super(uuid, username, accessToken, serverId, password, permissions);
|
||||||
this.username = username;
|
|
||||||
this.accessToken = accessToken;
|
|
||||||
this.serverId = serverId;
|
|
||||||
this.password = password;
|
|
||||||
this.permissions = permissions;
|
|
||||||
this.hwidId = hwidId;
|
this.hwidId = hwidId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getUsername() {
|
|
||||||
return username;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public UUID getUUID() {
|
|
||||||
return uuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getServerId() {
|
|
||||||
return serverId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getAccessToken() {
|
|
||||||
return accessToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ClientPermissions getPermissions() {
|
|
||||||
return permissions;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UserHardware getHardware() {
|
public UserHardware getHardware() {
|
||||||
if (hardware != null) return hardware;
|
if (hardware != null) return hardware;
|
||||||
|
@ -551,29 +338,4 @@ public String toString() {
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class MySQLUserSession implements UserSession {
|
|
||||||
private final MySQLUser user;
|
|
||||||
private final String id;
|
|
||||||
|
|
||||||
public MySQLUserSession(MySQLUser user) {
|
|
||||||
this.user = user;
|
|
||||||
this.id = user.username;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getID() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public User getUser() {
|
|
||||||
return user;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getExpireIn() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,297 +1,14 @@
|
||||||
package pro.gravit.launchserver.auth.core;
|
package pro.gravit.launchserver.auth.core;
|
||||||
|
|
||||||
import io.jsonwebtoken.ExpiredJwtException;
|
|
||||||
import io.jsonwebtoken.JwtException;
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
import pro.gravit.launcher.ClientPermissions;
|
|
||||||
import pro.gravit.launcher.request.auth.AuthRequest;
|
|
||||||
import pro.gravit.launcher.request.auth.password.AuthPlainPassword;
|
|
||||||
import pro.gravit.launchserver.LaunchServer;
|
import pro.gravit.launchserver.LaunchServer;
|
||||||
import pro.gravit.launchserver.auth.AuthException;
|
|
||||||
import pro.gravit.launchserver.auth.MySQLSourceConfig;
|
|
||||||
import pro.gravit.launchserver.auth.PostgreSQLSourceConfig;
|
import pro.gravit.launchserver.auth.PostgreSQLSourceConfig;
|
||||||
import pro.gravit.launchserver.auth.password.PasswordVerifier;
|
import pro.gravit.launchserver.auth.SQLSourceConfig;
|
||||||
import pro.gravit.launchserver.helper.LegacySessionHelper;
|
|
||||||
import pro.gravit.launchserver.manangers.AuthManager;
|
|
||||||
import pro.gravit.launchserver.socket.response.auth.AuthResponse;
|
|
||||||
import pro.gravit.utils.helper.SecurityHelper;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
public class PostgresSQLCoreProvider extends AbstractSQLCoreProvider {
|
||||||
import java.sql.*;
|
|
||||||
import java.time.Clock;
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public class PostgresSQLCoreProvider extends AuthCoreProvider {
|
|
||||||
private transient final Logger logger = LogManager.getLogger();
|
|
||||||
public PostgreSQLSourceConfig postgresSQLHolder;
|
public PostgreSQLSourceConfig postgresSQLHolder;
|
||||||
|
|
||||||
public int expireSeconds = 3600;
|
|
||||||
public String uuidColumn;
|
|
||||||
public String usernameColumn;
|
|
||||||
public String accessTokenColumn;
|
|
||||||
public String passwordColumn;
|
|
||||||
public String serverIDColumn;
|
|
||||||
public String table;
|
|
||||||
|
|
||||||
public PasswordVerifier passwordVerifier;
|
|
||||||
public String customQueryByUUIDSQL;
|
|
||||||
public String customQueryByUsernameSQL;
|
|
||||||
public String customQueryByLoginSQL;
|
|
||||||
public String customUpdateAuthSQL;
|
|
||||||
public String customUpdateServerIdSQL;
|
|
||||||
// Prepared SQL queries
|
|
||||||
private transient String queryByUUIDSQL;
|
|
||||||
private transient String queryByUsernameSQL;
|
|
||||||
private transient String queryByLoginSQL;
|
|
||||||
private transient String updateAuthSQL;
|
|
||||||
private transient String updateServerIDSQL;
|
|
||||||
|
|
||||||
private transient LaunchServer server;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public User getUserByUsername(String username) {
|
public SQLSourceConfig getSQLConfig() {
|
||||||
try {
|
return postgresSQLHolder;
|
||||||
return query(queryByUsernameSQL, username);
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.error("SQL error", e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public User getUserByUUID(UUID uuid) {
|
|
||||||
try {
|
|
||||||
return query(queryByUUIDSQL, uuid.toString());
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.error("SQL error", e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public User getUserByLogin(String login) {
|
|
||||||
try {
|
|
||||||
return query(queryByLoginSQL, login);
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.error("SQL error", e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public UserSession getUserSessionByOAuthAccessToken(String accessToken) throws OAuthAccessTokenExpired {
|
|
||||||
try {
|
|
||||||
var info = LegacySessionHelper.getJwtInfoFromAccessToken(accessToken, server.keyAgreementManager.ecdsaPublicKey);
|
|
||||||
var user = (PostgresSQLUser) getUserByUUID(info.uuid());
|
|
||||||
if(user == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return new PostgresSQLCoreProvider.MySQLUserSession(user);
|
|
||||||
} catch (ExpiredJwtException e) {
|
|
||||||
throw new OAuthAccessTokenExpired();
|
|
||||||
} catch (JwtException e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AuthManager.AuthReport refreshAccessToken(String refreshToken, AuthResponse.AuthContext context) {
|
|
||||||
String[] parts = refreshToken.split("\\.");
|
|
||||||
if(parts.length != 2) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
String username = parts[0];
|
|
||||||
String token = parts[1];
|
|
||||||
var user = (PostgresSQLUser) getUserByUsername(username);
|
|
||||||
if(user == null || user.password == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
var realToken = LegacySessionHelper.makeRefreshTokenFromPassword(username, user.password, server.keyAgreementManager.legacySalt);
|
|
||||||
if(!token.equals(realToken)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
var accessToken = LegacySessionHelper.makeAccessJwtTokenFromString(user, LocalDateTime.now(Clock.systemUTC()).plusSeconds(expireSeconds), server.keyAgreementManager.ecdsaPrivateKey);
|
|
||||||
return new AuthManager.AuthReport(null, accessToken, refreshToken, expireSeconds * 1000L, new PostgresSQLCoreProvider.MySQLUserSession(user));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AuthManager.AuthReport authorize(String login, AuthResponse.AuthContext context, AuthRequest.AuthPasswordInterface password, boolean minecraftAccess) throws IOException {
|
|
||||||
PostgresSQLUser postgresSQLUser = (PostgresSQLUser) getUserByLogin(login);
|
|
||||||
if(postgresSQLUser == null) {
|
|
||||||
throw AuthException.wrongPassword();
|
|
||||||
}
|
|
||||||
if(context != null) {
|
|
||||||
AuthPlainPassword plainPassword = (AuthPlainPassword) password;
|
|
||||||
if(plainPassword == null) {
|
|
||||||
throw AuthException.wrongPassword();
|
|
||||||
}
|
|
||||||
if(!passwordVerifier.check(postgresSQLUser.password, plainPassword.password)) {
|
|
||||||
throw AuthException.wrongPassword();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MySQLUserSession session = new MySQLUserSession(postgresSQLUser);
|
|
||||||
var accessToken = LegacySessionHelper.makeAccessJwtTokenFromString(postgresSQLUser, LocalDateTime.now(Clock.systemUTC()).plusSeconds(expireSeconds), server.keyAgreementManager.ecdsaPrivateKey);
|
|
||||||
var refreshToken = postgresSQLUser.username.concat(".").concat(LegacySessionHelper.makeRefreshTokenFromPassword(postgresSQLUser.username, postgresSQLUser.password, server.keyAgreementManager.legacySalt));
|
|
||||||
if (minecraftAccess) {
|
|
||||||
String minecraftAccessToken = SecurityHelper.randomStringToken();
|
|
||||||
updateAuth(postgresSQLUser, minecraftAccessToken);
|
|
||||||
return AuthManager.AuthReport.ofOAuthWithMinecraft(minecraftAccessToken, accessToken, refreshToken, expireSeconds * 1000L, session);
|
|
||||||
} else {
|
|
||||||
return AuthManager.AuthReport.ofOAuth(accessToken, refreshToken, expireSeconds * 1000L, session);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init(LaunchServer server) {
|
|
||||||
this.server = server;
|
|
||||||
if (postgresSQLHolder == null) logger.error("postgresSQLHolder cannot be null");
|
|
||||||
if (uuidColumn == null) logger.error("uuidColumn cannot be null");
|
|
||||||
if (usernameColumn == null) logger.error("usernameColumn cannot be null");
|
|
||||||
if (accessTokenColumn == null) logger.error("accessTokenColumn cannot be null");
|
|
||||||
if (serverIDColumn == null) logger.error("serverIDColumn cannot be null");
|
|
||||||
if (table == null) logger.error("table cannot be null");
|
|
||||||
// Prepare SQL queries
|
|
||||||
String userInfoCols = String.format("%s, %s, %s, %s, %s", uuidColumn, usernameColumn, accessTokenColumn, serverIDColumn, passwordColumn);
|
|
||||||
queryByUUIDSQL = customQueryByUUIDSQL != null ? customQueryByUUIDSQL : String.format("SELECT %s FROM %s WHERE %s=? LIMIT 1", userInfoCols,
|
|
||||||
table, uuidColumn);
|
|
||||||
queryByUsernameSQL = customQueryByUsernameSQL != null ? customQueryByUsernameSQL : String.format("SELECT %s FROM %s WHERE %s=? LIMIT 1",
|
|
||||||
userInfoCols, table, usernameColumn);
|
|
||||||
queryByLoginSQL = customQueryByLoginSQL != null ? customQueryByLoginSQL : queryByUsernameSQL;
|
|
||||||
|
|
||||||
updateAuthSQL = customUpdateAuthSQL != null ? customUpdateAuthSQL : String.format("UPDATE %s SET %s=?, %s=NULL WHERE %s=?",
|
|
||||||
table, accessTokenColumn, serverIDColumn, uuidColumn);
|
|
||||||
updateServerIDSQL = customUpdateServerIdSQL != null ? customUpdateServerIdSQL : String.format("UPDATE %s SET %s=? WHERE %s=?",
|
|
||||||
table, serverIDColumn, uuidColumn);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean updateAuth(User user, String accessToken) throws IOException {
|
|
||||||
try (Connection c = postgresSQLHolder.getConnection()) {
|
|
||||||
PostgresSQLUser postgresSQLUser = (PostgresSQLUser) user;
|
|
||||||
postgresSQLUser.accessToken = accessToken;
|
|
||||||
PreparedStatement s = c.prepareStatement(updateAuthSQL);
|
|
||||||
s.setString(1, accessToken);
|
|
||||||
s.setString(2, user.getUUID().toString());
|
|
||||||
s.setQueryTimeout(MySQLSourceConfig.TIMEOUT);
|
|
||||||
return s.executeUpdate() > 0;
|
|
||||||
} catch (SQLException e) {
|
|
||||||
throw new IOException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean updateServerID(User user, String serverID) throws IOException {
|
|
||||||
try (Connection c = postgresSQLHolder.getConnection()) {
|
|
||||||
PostgresSQLUser postgresSQLUser = (PostgresSQLUser) user;
|
|
||||||
postgresSQLUser.serverId = serverID;
|
|
||||||
PreparedStatement s = c.prepareStatement(updateServerIDSQL);
|
|
||||||
s.setString(1, serverID);
|
|
||||||
s.setString(2, user.getUUID().toString());
|
|
||||||
s.setQueryTimeout(MySQLSourceConfig.TIMEOUT);
|
|
||||||
return s.executeUpdate() > 0;
|
|
||||||
} catch (SQLException e) {
|
|
||||||
throw new IOException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() throws IOException {
|
|
||||||
postgresSQLHolder.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
private PostgresSQLUser constructUser(ResultSet set) throws SQLException {
|
|
||||||
return set.next() ? new PostgresSQLUser(UUID.fromString(set.getString(uuidColumn)), set.getString(usernameColumn),
|
|
||||||
set.getString(accessTokenColumn), set.getString(serverIDColumn), set.getString(passwordColumn), new ClientPermissions()) : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private User query(String sql, String value) throws IOException {
|
|
||||||
try (Connection c = postgresSQLHolder.getConnection()) {
|
|
||||||
PreparedStatement s = c.prepareStatement(sql);
|
|
||||||
s.setString(1, value);
|
|
||||||
s.setQueryTimeout(MySQLSourceConfig.TIMEOUT);
|
|
||||||
try (ResultSet set = s.executeQuery()) {
|
|
||||||
return constructUser(set);
|
|
||||||
}
|
|
||||||
} catch (SQLException e) {
|
|
||||||
throw new IOException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class PostgresSQLUser implements User {
|
|
||||||
protected UUID uuid;
|
|
||||||
protected String username;
|
|
||||||
protected String accessToken;
|
|
||||||
protected String serverId;
|
|
||||||
protected String password;
|
|
||||||
protected ClientPermissions permissions;
|
|
||||||
|
|
||||||
public PostgresSQLUser(UUID uuid, String username, String accessToken, String serverId, String password, ClientPermissions permissions) {
|
|
||||||
this.uuid = uuid;
|
|
||||||
this.username = username;
|
|
||||||
this.accessToken = accessToken;
|
|
||||||
this.serverId = serverId;
|
|
||||||
this.password = password;
|
|
||||||
this.permissions = permissions;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getUsername() {
|
|
||||||
return username;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public UUID getUUID() {
|
|
||||||
return uuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getServerId() {
|
|
||||||
return serverId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getAccessToken() {
|
|
||||||
return accessToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ClientPermissions getPermissions() {
|
|
||||||
return permissions;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "PostgresSQLUser{" +
|
|
||||||
"uuid=" + uuid +
|
|
||||||
", username='" + username + '\'' +
|
|
||||||
", permissions=" + permissions +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class MySQLUserSession implements UserSession {
|
|
||||||
private final PostgresSQLUser user;
|
|
||||||
private final String id;
|
|
||||||
|
|
||||||
public MySQLUserSession(PostgresSQLUser user) {
|
|
||||||
this.user = user;
|
|
||||||
this.id = user.username;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getID() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public User getUser() {
|
|
||||||
return user;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getExpireIn() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue