From 8908710ad675c5c2a56108f57ae90d63eaa5d56c Mon Sep 17 00:00:00 2001 From: XakepSDK Date: Wed, 24 Apr 2024 18:21:16 +0500 Subject: [PATCH 01/15] [ANY] Add OpenID auth module (#709) Co-authored-by: d3coder --- LaunchServer/build.gradle | 1 + .../launchserver/auth/AuthException.java | 4 + .../auth/HikariSQLSourceConfig.java | 50 ++++ .../auth/core/AuthCoreProvider.java | 2 + .../auth/core/openid/AccessTokenResponse.java | 14 ++ .../core/openid/OpenIDAuthCoreProvider.java | 178 ++++++++++++++ .../auth/core/openid/OpenIDAuthenticator.java | 229 ++++++++++++++++++ .../auth/core/openid/OpenIDConfig.java | 9 + .../auth/core/openid/QueryBuilder.java | 59 +++++ .../core/openid/SQLServerSessionStore.java | 99 ++++++++ .../auth/core/openid/SQLUserStore.java | 124 ++++++++++ .../auth/core/openid/ServerSessionStore.java | 8 + .../auth/core/openid/TokenResponse.java | 5 + .../auth/core/openid/UserEntity.java | 23 ++ .../auth/core/openid/UserStore.java | 13 + props.gradle | 1 + 16 files changed, 819 insertions(+) create mode 100644 LaunchServer/src/main/java/pro/gravit/launchserver/auth/HikariSQLSourceConfig.java create mode 100644 LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/AccessTokenResponse.java create mode 100644 LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/OpenIDAuthCoreProvider.java create mode 100644 LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/OpenIDAuthenticator.java create mode 100644 LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/OpenIDConfig.java create mode 100644 LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/QueryBuilder.java create mode 100644 LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/SQLServerSessionStore.java create mode 100644 LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/SQLUserStore.java create mode 100644 LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/ServerSessionStore.java create mode 100644 LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/TokenResponse.java create mode 100644 LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/UserEntity.java create mode 100644 LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/UserStore.java diff --git a/LaunchServer/build.gradle b/LaunchServer/build.gradle index 6743d5ec..44b75deb 100644 --- a/LaunchServer/build.gradle +++ b/LaunchServer/build.gradle @@ -84,6 +84,7 @@ pack project(':LauncherAPI') bundle group: 'org.slf4j', name: 'slf4j-api', version: rootProject['verSlf4j'] bundle group: 'com.mysql', name: 'mysql-connector-j', version: rootProject['verMySQLConn'] bundle group: 'org.postgresql', name: 'postgresql', version: rootProject['verPostgreSQLConn'] + bundle group: 'com.h2database', name: 'h2', version: rootProject['verH2Conn'] bundle group: 'com.guardsquare', name: 'proguard-base', version: rootProject['verProguard'] bundle group: 'org.apache.logging.log4j', name: 'log4j-core', version: rootProject['verLog4j'] bundle group: 'org.apache.logging.log4j', name: 'log4j-slf4j2-impl', version: rootProject['verLog4j'] diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/AuthException.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/AuthException.java index e30f9842..ecf6ab0c 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/AuthException.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/AuthException.java @@ -16,6 +16,10 @@ public AuthException(String message) { super(message); } + public AuthException(String message, Throwable cause) { + super(message, cause); + } + public static AuthException need2FA() { return new AuthException(AuthRequestEvent.TWO_FACTOR_NEED_ERROR_MESSAGE); } diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/HikariSQLSourceConfig.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/HikariSQLSourceConfig.java new file mode 100644 index 00000000..974ce17e --- /dev/null +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/HikariSQLSourceConfig.java @@ -0,0 +1,50 @@ +package pro.gravit.launchserver.auth; + +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; + +import java.sql.Connection; +import java.sql.SQLException; +import java.util.Properties; +import java.util.function.Consumer; + +public class HikariSQLSourceConfig implements SQLSourceConfig { + private transient HikariDataSource dataSource; + private String dsClass; + private Properties dsProps; + private String driverClass; + private String jdbcUrl; + private String username; + private String password; + + public void init() { + if (dataSource != null) { + return; + } + HikariConfig config = new HikariConfig(); + consumeIfNotNull(config::setDataSourceClassName, dsClass); + consumeIfNotNull(config::setDataSourceProperties, dsProps); + consumeIfNotNull(config::setDriverClassName, driverClass); + consumeIfNotNull(config::setJdbcUrl, jdbcUrl); + consumeIfNotNull(config::setUsername, username); + consumeIfNotNull(config::setPassword, password); + + this.dataSource = new HikariDataSource(config); + } + + @Override + public Connection getConnection() throws SQLException { + return dataSource.getConnection(); + } + + @Override + public void close() { + dataSource.close(); + } + + private static void consumeIfNotNull(Consumer consumer, T val) { + if (val != null) { + consumer.accept(val); + } + } +} diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/AuthCoreProvider.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/AuthCoreProvider.java index b6e14d8d..806b657d 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/AuthCoreProvider.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/AuthCoreProvider.java @@ -21,6 +21,7 @@ import pro.gravit.launchserver.auth.core.interfaces.provider.AuthSupportHardware; import pro.gravit.launchserver.auth.core.interfaces.provider.AuthSupportRegistration; import pro.gravit.launchserver.auth.core.interfaces.provider.AuthSupportSudo; +import pro.gravit.launchserver.auth.core.openid.OpenIDAuthCoreProvider; import pro.gravit.launchserver.manangers.AuthManager; import pro.gravit.launchserver.socket.Client; import pro.gravit.launchserver.socket.response.auth.AuthResponse; @@ -53,6 +54,7 @@ public static void registerProviders() { providers.register("postgresql", PostgresSQLCoreProvider.class); providers.register("memory", MemoryAuthCoreProvider.class); providers.register("merge", MergeAuthCoreProvider.class); + providers.register("openid", OpenIDAuthCoreProvider.class); registredProviders = true; } } diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/AccessTokenResponse.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/AccessTokenResponse.java new file mode 100644 index 00000000..8a1d3f97 --- /dev/null +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/AccessTokenResponse.java @@ -0,0 +1,14 @@ +package pro.gravit.launchserver.auth.core.openid; + +import com.google.gson.annotations.SerializedName; + +public record AccessTokenResponse(@SerializedName("access_token") String accessToken, + @SerializedName("expires_in") Long expiresIn, + @SerializedName("refresh_expires_in") Long refreshExpiresIn, + @SerializedName("refresh_token") String refreshToken, + @SerializedName("token_type") String tokenType, + @SerializedName("id_token") String idToken, + @SerializedName("not-before-policy") Integer notBeforePolicy, + @SerializedName("session_state") String sessionState, + @SerializedName("scope") String scope) { +} diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/OpenIDAuthCoreProvider.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/OpenIDAuthCoreProvider.java new file mode 100644 index 00000000..77233f26 --- /dev/null +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/OpenIDAuthCoreProvider.java @@ -0,0 +1,178 @@ +package pro.gravit.launchserver.auth.core.openid; + +import io.jsonwebtoken.JwtException; +import io.jsonwebtoken.Jwts; +import pro.gravit.launcher.base.ClientPermissions; +import pro.gravit.launcher.base.events.request.GetAvailabilityAuthRequestEvent; +import pro.gravit.launcher.base.request.auth.AuthRequest; +import pro.gravit.launcher.base.request.auth.password.AuthCodePassword; +import pro.gravit.launchserver.LaunchServer; +import pro.gravit.launchserver.auth.AuthException; +import pro.gravit.launchserver.auth.AuthProviderPair; +import pro.gravit.launchserver.auth.HikariSQLSourceConfig; +import pro.gravit.launchserver.auth.core.AuthCoreProvider; +import pro.gravit.launchserver.auth.core.User; +import pro.gravit.launchserver.auth.core.UserSession; +import pro.gravit.launchserver.manangers.AuthManager; +import pro.gravit.launchserver.socket.Client; +import pro.gravit.launchserver.socket.response.auth.AuthResponse; +import pro.gravit.utils.helper.LogHelper; + +import java.io.IOException; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.Date; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.TimeUnit; + +public class OpenIDAuthCoreProvider extends AuthCoreProvider { + private transient SQLUserStore sqlUserStore; + private transient SQLServerSessionStore sqlSessionStore; + private transient OpenIDAuthenticator openIDAuthenticator; + + private OpenIDConfig openIDConfig; + private HikariSQLSourceConfig sqlSourceConfig; + + @Override + public List getDetails(Client client) { + return openIDAuthenticator.getDetails(); + } + + @Override + public User getUserByUsername(String username) { + return sqlUserStore.getByUsername(username); + } + + @Override + public User getUserByUUID(UUID uuid) { + return sqlUserStore.getUserByUUID(uuid); + } + + @Override + public UserSession getUserSessionByOAuthAccessToken(String accessToken) throws OAuthAccessTokenExpired { + return openIDAuthenticator.getUserSessionByOAuthAccessToken(accessToken); + } + + @Override + public AuthManager.AuthReport refreshAccessToken(String oldRefreshToken, AuthResponse.AuthContext context) { + var tokens = openIDAuthenticator.refreshAccessToken(oldRefreshToken); + var accessToken = tokens.accessToken(); + var refreshToken = tokens.refreshToken(); + long expiresIn = TimeUnit.SECONDS.toMillis(tokens.accessTokenExpiresIn()); + + UserSession session; + try { + session = openIDAuthenticator.getUserSessionByOAuthAccessToken(accessToken); + } catch (OAuthAccessTokenExpired e) { + throw new RuntimeException("invalid token", e); + } + + + return AuthManager.AuthReport.ofOAuth(accessToken, refreshToken, + expiresIn, session); + } + + @Override + public AuthManager.AuthReport authorize(String login, AuthResponse.AuthContext context, AuthRequest.AuthPasswordInterface password, boolean minecraftAccess) throws IOException { + if (password == null) { + throw AuthException.wrongPassword(); + } + var authCodePassword = (AuthCodePassword) password; + + var tokens = openIDAuthenticator.authorize(authCodePassword); + + var accessToken = tokens.accessToken(); + var refreshToken = tokens.refreshToken(); + var user = openIDAuthenticator.createUserFromToken(accessToken); + long expiresIn = TimeUnit.SECONDS.toMillis(tokens.accessTokenExpiresIn()); + + sqlUserStore.createOrUpdateUser(user); + + UserSession session; + try { + session = openIDAuthenticator.getUserSessionByOAuthAccessToken(accessToken); + } catch (OAuthAccessTokenExpired e) { + throw new AuthException("invalid token", e); + } + + if (minecraftAccess) { + var minecraftToken = generateMinecraftToken(user); + return AuthManager.AuthReport.ofOAuthWithMinecraft(minecraftToken, accessToken, refreshToken, + expiresIn, session); + } else { + return AuthManager.AuthReport.ofOAuth(accessToken, refreshToken, + expiresIn, session); + } + } + + private String generateMinecraftToken(User user) { + return Jwts.builder() + .issuer("LaunchServer") + .subject(user.getUUID().toString()) + .claim("preferred_username", user.getUsername()) + .expiration(Date.from(Instant.now().plus(24, ChronoUnit.HOURS))) + .signWith(server.keyAgreementManager.ecdsaPrivateKey) + .compact(); + } + + private User createUserFromMinecraftToken(String accessToken) throws AuthException { + try { + var parser = Jwts.parser() + .requireIssuer("LaunchServer") + .verifyWith(server.keyAgreementManager.ecdsaPublicKey) + .build(); + var claims = parser.parseSignedClaims(accessToken); + var username = claims.getPayload().get("preferred_username", String.class); + var uuid = UUID.fromString(claims.getPayload().getSubject()); + return new UserEntity(username, uuid, new ClientPermissions()); + } catch (JwtException e) { + throw new AuthException("Bad minecraft token", e); + } + } + + @Override + public void init(LaunchServer server, AuthProviderPair pair) { + super.init(server, pair); + this.sqlSourceConfig.init(); + this.sqlUserStore = new SQLUserStore(sqlSourceConfig); + this.sqlUserStore.init(); + this.sqlSessionStore = new SQLServerSessionStore(sqlSourceConfig); + this.sqlSessionStore.init(); + this.openIDAuthenticator = new OpenIDAuthenticator(openIDConfig); + } + + @Override + public User checkServer(Client client, String username, String serverID) throws IOException { + var savedServerId = sqlSessionStore.getServerIdByUsername(username); + if (!serverID.equals(savedServerId)) { + return null; + } + + return sqlUserStore.getByUsername(username); + } + + @Override + public boolean joinServer(Client client, String username, UUID uuid, String accessToken, String serverID) throws IOException { + User user; + try { + user = createUserFromMinecraftToken(accessToken); + } catch (AuthException e) { + LogHelper.error(e); + return false; + } + if (!user.getUUID().equals(uuid)) { + return false; + } + + sqlUserStore.createOrUpdateUser(user); + + return sqlSessionStore.joinServer(user.getUUID(), user.getUsername(), serverID); + } + + @Override + public void close() { + sqlSourceConfig.close(); + } + +} diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/OpenIDAuthenticator.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/OpenIDAuthenticator.java new file mode 100644 index 00000000..5e0f9e0b --- /dev/null +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/OpenIDAuthenticator.java @@ -0,0 +1,229 @@ +package pro.gravit.launchserver.auth.core.openid; + +import io.jsonwebtoken.*; +import io.jsonwebtoken.security.Jwk; +import io.jsonwebtoken.security.JwkSet; +import io.jsonwebtoken.security.Jwks; +import pro.gravit.launcher.base.ClientPermissions; +import pro.gravit.launcher.base.Launcher; +import pro.gravit.launcher.base.events.request.GetAvailabilityAuthRequestEvent; +import pro.gravit.launcher.base.request.auth.details.AuthWebViewDetails; +import pro.gravit.launcher.base.request.auth.password.AuthCodePassword; +import pro.gravit.launchserver.auth.AuthException; +import pro.gravit.launchserver.auth.core.AuthCoreProvider; +import pro.gravit.launchserver.auth.core.User; +import pro.gravit.launchserver.auth.core.UserSession; +import pro.gravit.utils.helper.CommonHelper; +import pro.gravit.utils.helper.QueryHelper; + +import java.io.IOException; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.security.Key; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.UUID; +import java.util.stream.Collectors; + +public class OpenIDAuthenticator { + private static final HttpClient CLIENT = HttpClient.newBuilder().build(); + private final OpenIDConfig openIDConfig; + private final JwtParser jwtParser; + + public OpenIDAuthenticator(OpenIDConfig openIDConfig) { + this.openIDConfig = openIDConfig; + var keyLocator = loadKeyLocator(openIDConfig); + this.jwtParser = Jwts.parser().keyLocator(keyLocator) + .build(); + } + + public List getDetails() { + var state = UUID.randomUUID().toString(); + var uri = QueryBuilder.get(openIDConfig.authorizationEndpoint()) + .addQuery("response_type", "code") + .addQuery("client_id", openIDConfig.clientId()) + .addQuery("redirect_uri", openIDConfig.redirectUri()) + .addQuery("scope", openIDConfig.scopes()) + .addQuery("state", state) + .toUriString(); + + return List.of(new AuthWebViewDetails(uri, openIDConfig.redirectUri())); + } + + public TokenResponse refreshAccessToken(String oldRefreshToken) { + var postBody = QueryBuilder.post() + .addQuery("grant_type", "refresh_token") + .addQuery("refresh_token", oldRefreshToken) + .addQuery("client_id", openIDConfig.clientId()) + .addQuery("client_secret", openIDConfig.clientSecret()) + .toString(); + + var accessTokenResponse = requestToken(postBody); + var accessToken = accessTokenResponse.accessToken(); + var refreshToken = accessTokenResponse.refreshToken(); + + try { + readAndVerifyToken(accessToken); + } catch (AuthException e) { + throw new RuntimeException(e); + } + + var accessTokenExpiresIn = Objects.requireNonNullElse(accessTokenResponse.expiresIn(), 0L); + var refreshTokenExpiresIn = Objects.requireNonNullElse(accessTokenResponse.refreshExpiresIn(), 0L); + + return new TokenResponse(accessToken, accessTokenExpiresIn, + refreshToken, refreshTokenExpiresIn); + } + + public UserSession getUserSessionByOAuthAccessToken(String accessToken) throws AuthCoreProvider.OAuthAccessTokenExpired { + Jws token; + try { + token = readAndVerifyToken(accessToken); + } catch (AuthException e) { + throw new AuthCoreProvider.OAuthAccessTokenExpired("Can't read token", e); + } + var user = createUserFromToken(token); + long expiresIn = 0; + var expDate = token.getPayload().getExpiration(); + if (expDate != null) { + expiresIn = expDate.toInstant().toEpochMilli(); + } + + return new OpenIDUserSession(user, accessToken, expiresIn); + } + + public TokenResponse authorize(AuthCodePassword authCode) throws IOException { + var uri = URI.create(authCode.uri); + var queries = QueryHelper.splitUriQuery(uri); + + String code = CommonHelper.multimapFirstOrNullValue("code", queries); + String error = CommonHelper.multimapFirstOrNullValue("error", queries); + String errorDescription = CommonHelper.multimapFirstOrNullValue("error_description", queries); + + if (error != null && !error.isBlank()) { + throw new AuthException("Auth error. Error: %s, description: %s".formatted(error, errorDescription)); + } + + + var postBody = QueryBuilder.post() + .addQuery("grant_type", "authorization_code") + .addQuery("code", code) + .addQuery("redirect_uri", openIDConfig.redirectUri()) + .addQuery("client_id", openIDConfig.clientId()) + .addQuery("client_secret", openIDConfig.clientSecret()) + .toString(); + + var accessTokenResponse = requestToken(postBody); + var accessToken = accessTokenResponse.accessToken(); + var refreshToken = accessTokenResponse.refreshToken(); + + readAndVerifyToken(accessToken); + + var accessTokenExpiresIn = Objects.requireNonNullElse(accessTokenResponse.expiresIn(), 0L); + var refreshTokenExpiresIn = Objects.requireNonNullElse(accessTokenResponse.refreshExpiresIn(), 0L); + + return new TokenResponse(accessToken, accessTokenExpiresIn, + refreshToken, refreshTokenExpiresIn); + } + + public User createUserFromToken(String accessToken) throws AuthException { + return createUserFromToken(readAndVerifyToken(accessToken)); + } + + private Jws readAndVerifyToken(String accessToken) throws AuthException { + if (accessToken == null) { + throw new AuthException("Token is null"); + } + + try { + return jwtParser.parseSignedClaims(accessToken); + } catch (JwtException e) { + throw new AuthException("Bad token", e); + } + } + + private User createUserFromToken(Jws token) { + var username = token.getPayload().get(openIDConfig.extractorConfig().usernameClaim(), String.class); + var uuidStr = token.getPayload().get(openIDConfig.extractorConfig().uuidClaim(), String.class); + var uuid = UUID.fromString(uuidStr); + return new UserEntity(username, uuid, new ClientPermissions()); + } + + private AccessTokenResponse requestToken(String postBody) { + var request = HttpRequest.newBuilder() + .uri(openIDConfig.tokenUri()) + .header("Content-Type", "application/x-www-form-urlencoded") + .header("Accept", "application/json") + .POST(HttpRequest.BodyPublishers.ofString(postBody)) + .build(); + + HttpResponse resp; + try { + resp = CLIENT.send(request, HttpResponse.BodyHandlers.ofString()); + } catch (IOException | InterruptedException e) { + throw new RuntimeException(e); + } + return Launcher.gsonManager.gson.fromJson(resp.body(), AccessTokenResponse.class); + } + + private static KeyLocator loadKeyLocator(OpenIDConfig openIDConfig) { + var request = HttpRequest.newBuilder(openIDConfig.jwksUri()).GET().build(); + HttpResponse response; + try { + response = CLIENT.send(request, HttpResponse.BodyHandlers.ofString()); + } catch (IOException | InterruptedException e) { + throw new RuntimeException(e); + } + var jwks = Jwks.setParser().build().parse(response.body()); + return new KeyLocator(jwks); + } + + private static class KeyLocator extends LocatorAdapter { + private final Map keys; + + public KeyLocator(JwkSet jwks) { + this.keys = jwks.getKeys().stream().collect( + Collectors.toMap(jwk -> String.valueOf(jwk.get("kid")), Jwk::toKey)); + } + + @Override + protected Key locate(JweHeader header) { + return super.locate(header); + } + + @Override + protected Key locate(JwsHeader header) { + return keys.get(header.getKeyId()); + } + + @Override + protected Key doLocate(Header header) { + return super.doLocate(header); + } + } + + record OpenIDUserSession(User user, String token, long expiresIn) implements UserSession { + @Override + public String getID() { + return user.getUsername(); + } + + @Override + public User getUser() { + return user; + } + + @Override + public String getMinecraftAccessToken() { + return token; + } + + @Override + public long getExpireIn() { + return expiresIn; + } + } +} diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/OpenIDConfig.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/OpenIDConfig.java new file mode 100644 index 00000000..395f2046 --- /dev/null +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/OpenIDConfig.java @@ -0,0 +1,9 @@ +package pro.gravit.launchserver.auth.core.openid; + +import java.net.URI; + +public record OpenIDConfig(URI tokenUri, String authorizationEndpoint, String clientId, String clientSecret, + String redirectUri, URI jwksUri, String scopes, ClaimExtractorConfig extractorConfig) { + + public record ClaimExtractorConfig(String usernameClaim, String uuidClaim) {} +} diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/QueryBuilder.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/QueryBuilder.java new file mode 100644 index 00000000..c3175ffc --- /dev/null +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/QueryBuilder.java @@ -0,0 +1,59 @@ +package pro.gravit.launchserver.auth.core.openid; + +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.Objects; + +/** + * @author Xakep_SDK + */ +public class QueryBuilder { + private final String uri; + private final StringBuilder query = new StringBuilder(); + + public QueryBuilder(String uri) { + this.uri = uri; + } + + public static QueryBuilder get(String uri) { + Objects.requireNonNull(uri, "uri"); + if (uri.endsWith("/")) { + uri = uri.substring(0, uri.length() - 1); + } + return new QueryBuilder(uri); + } + + public static QueryBuilder post() { + return new QueryBuilder(null); + } + + public QueryBuilder addQuery(String key, String value) { + if (!query.isEmpty()) { + query.append('&'); + } + query.append(URLEncoder.encode(key, StandardCharsets.UTF_8)) + .append('=') + .append(URLEncoder.encode(value, StandardCharsets.UTF_8)); + return this; + } + + public String toUriString() { + if (uri != null) { + if (query. isEmpty()) { + return uri; + } + return uri + '?' + query; + } + return toQueryString(); + } + + public String toQueryString() { + return query.toString(); + } + + @Override + public String toString() { + return toUriString(); + } +} + diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/SQLServerSessionStore.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/SQLServerSessionStore.java new file mode 100644 index 00000000..6acebc5d --- /dev/null +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/SQLServerSessionStore.java @@ -0,0 +1,99 @@ +package pro.gravit.launchserver.auth.core.openid; + +import pro.gravit.launchserver.auth.SQLSourceConfig; +import pro.gravit.utils.helper.LogHelper; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.sql.SQLException; +import java.util.UUID; + +public class SQLServerSessionStore implements ServerSessionStore { + private static final String CREATE_TABLE = """ + create table if not exists `gravit_server_session` ( + id int auto_increment, + uuid varchar(36), + username varchar(255), + server_id varchar(41), + primary key (id), + unique (uuid), + unique (username) + ); + """; + private static final String DELETE_SERVER_ID = """ + delete from `gravit_server_session` where uuid = ? + """; + private static final String INSERT_SERVER_ID = """ + insert into `gravit_server_session` (uuid, username, server_id) values (?, ?, ?) + """; + private static final String SELECT_SERVER_ID_BY_USERNAME = """ + select server_id from `gravit_server_session` where username = ? + """; + + private final SQLSourceConfig sqlSourceConfig; + + public SQLServerSessionStore(SQLSourceConfig sqlSourceConfig) { + this.sqlSourceConfig = sqlSourceConfig; + } + + @Override + public boolean joinServer(UUID uuid, String username, String serverId) { + try (var connection = sqlSourceConfig.getConnection()) { + connection.setAutoCommit(false); + var savepoint = connection.setSavepoint(); + try (var deleteServerIdStmt = connection.prepareStatement(DELETE_SERVER_ID); + var insertServerIdStmt = connection.prepareStatement(INSERT_SERVER_ID)) { + deleteServerIdStmt.setString(1, uuid.toString()); + deleteServerIdStmt.execute(); + insertServerIdStmt.setString(1, uuid.toString()); + insertServerIdStmt.setString(2, username); + insertServerIdStmt.setString(3, serverId); + insertServerIdStmt.execute(); + connection.commit(); + return true; + } catch (Exception e) { + connection.rollback(savepoint); + throw e; + } + } catch (SQLException e) { + LogHelper.debug("Can't join server. Username: %s".formatted(username)); + LogHelper.error(e); + } + + return false; + } + + @Override + public String getServerIdByUsername(String username) { + try (var connection = sqlSourceConfig.getConnection(); + var selectServerId = connection.prepareStatement(SELECT_SERVER_ID_BY_USERNAME)) { + selectServerId.setString(1, username); + try (var rs = selectServerId.executeQuery()) { + if (!rs.next()) { + return null; + } + return rs.getString("server_id"); + } + } catch (SQLException e) { + LogHelper.debug("Can't find server id by username. Username: %s".formatted(username)); + LogHelper.error(e); + } + return null; + } + + public void init() { + try (var connection = sqlSourceConfig.getConnection()) { + connection.setAutoCommit(false); + var savepoint = connection.setSavepoint(); + try (var createTableStmt = connection.prepareStatement(CREATE_TABLE)) { + createTableStmt.execute(); + connection.commit(); + } catch (Exception e) { + connection.rollback(savepoint); + throw e; + } + } catch (SQLException e) { + throw new RuntimeException(e); + } + } +} diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/SQLUserStore.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/SQLUserStore.java new file mode 100644 index 00000000..3ac59b2d --- /dev/null +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/SQLUserStore.java @@ -0,0 +1,124 @@ +package pro.gravit.launchserver.auth.core.openid; + +import pro.gravit.launcher.base.ClientPermissions; +import pro.gravit.launchserver.auth.HikariSQLSourceConfig; +import pro.gravit.launchserver.auth.core.User; +import pro.gravit.utils.helper.LogHelper; + +import java.sql.SQLException; +import java.util.UUID; + +public class SQLUserStore implements UserStore { + private static final String CREATE_USER_TABLE = """ + create table if not exists `gravit_user` ( + id int auto_increment, + uuid varchar(36), + username varchar(255), + primary key (id), + unique (uuid), + unique (username) + ) + """; + private static final String INSERT_USER = """ + insert into `gravit_user` (uuid, username) values (?, ?) + """; + private static final String DELETE_USER_BY_NAME = """ + delete `gravit_user` where username = ? + """; + private static final String SELECT_USER_BY_NAME = """ + select uuid, username from `gravit_user` where username = ? + """; + private static final String SELECT_USER_BY_UUID = """ + select uuid, username from `gravit_user` where uuid = ? + """; + + private final HikariSQLSourceConfig sqlSourceConfig; + + public SQLUserStore(HikariSQLSourceConfig sqlSourceConfig) { + this.sqlSourceConfig = sqlSourceConfig; + } + + @Override + public User getByUsername(String username) { + try (var connection = sqlSourceConfig.getConnection(); + var selectUserStmt = connection.prepareStatement(SELECT_USER_BY_NAME)) { + selectUserStmt.setString(1, username); + try (var rs = selectUserStmt.executeQuery()) { + if (!rs.next()) { + LogHelper.debug("User not found, username: %s".formatted(username)); + return null; + } + return new UserEntity(rs.getString("username"), + UUID.fromString(rs.getString("uuid")), + new ClientPermissions()); + } + } catch (SQLException e) { + LogHelper.error(e); + } + + return null; + } + + @Override + public User getUserByUUID(UUID uuid) { + try (var connection = sqlSourceConfig.getConnection(); + var selectUserStmt = connection.prepareStatement(SELECT_USER_BY_UUID)) { + selectUserStmt.setString(1, uuid.toString()); + try (var rs = selectUserStmt.executeQuery()) { + if (!rs.next()) { + LogHelper.debug("User not found, UUID: %s".formatted(uuid)); + return null; + } + return new UserEntity(rs.getString("username"), + UUID.fromString(rs.getString("uuid")), + new ClientPermissions()); + } + } catch (SQLException e) { + LogHelper.error(e); + } + + return null; + } + + @Override + public void createOrUpdateUser(User user) { + try (var connection = sqlSourceConfig.getConnection()) { + connection.setAutoCommit(false); + var savepoint = connection.setSavepoint(); + try (var deleteUserStmt = connection.prepareStatement(DELETE_USER_BY_NAME); + var insertUserStmt = connection.prepareStatement(INSERT_USER)) { + deleteUserStmt.setString(1, user.getUsername()); + deleteUserStmt.execute(); + insertUserStmt.setString(1, user.getUUID().toString()); + insertUserStmt.setString(2, user.getUsername()); + insertUserStmt.execute(); + connection.commit(); + LogHelper.debug("User saved. UUID: %s, username: %s".formatted(user.getUUID(), user.getUsername())); + } catch (Exception e) { + connection.rollback(savepoint); + throw e; + } + } catch (SQLException e) { + LogHelper.debug("Failed to save user"); + LogHelper.error(e); + throw new RuntimeException("Failed to save user", e); + } + } + + public void init() { + try (var connection = sqlSourceConfig.getConnection()) { + connection.setAutoCommit(false); + var savepoint = connection.setSavepoint(); + try (var createUserTableStmt = connection.prepareStatement(CREATE_USER_TABLE)) { + createUserTableStmt.execute(); + connection.commit(); + } catch (Exception e) { + connection.rollback(savepoint); + throw e; + } + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + +} diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/ServerSessionStore.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/ServerSessionStore.java new file mode 100644 index 00000000..cf049951 --- /dev/null +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/ServerSessionStore.java @@ -0,0 +1,8 @@ +package pro.gravit.launchserver.auth.core.openid; + +import java.util.UUID; + +public interface ServerSessionStore { + boolean joinServer(UUID uuid, String username, String serverId); + String getServerIdByUsername(String username); +} diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/TokenResponse.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/TokenResponse.java new file mode 100644 index 00000000..4775213c --- /dev/null +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/TokenResponse.java @@ -0,0 +1,5 @@ +package pro.gravit.launchserver.auth.core.openid; + +public record TokenResponse(String accessToken, long accessTokenExpiresIn, + String refreshToken, long refreshTokenExpiresIn) { +} diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/UserEntity.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/UserEntity.java new file mode 100644 index 00000000..f383a16c --- /dev/null +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/UserEntity.java @@ -0,0 +1,23 @@ +package pro.gravit.launchserver.auth.core.openid; + +import pro.gravit.launcher.base.ClientPermissions; +import pro.gravit.launchserver.auth.core.User; + +import java.util.UUID; + +record UserEntity(String username, UUID uuid, ClientPermissions permissions) implements User { + @Override + public String getUsername() { + return username; + } + + @Override + public UUID getUUID() { + return uuid; + } + + @Override + public ClientPermissions getPermissions() { + return permissions; + } +} diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/UserStore.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/UserStore.java new file mode 100644 index 00000000..55c26e71 --- /dev/null +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/UserStore.java @@ -0,0 +1,13 @@ +package pro.gravit.launchserver.auth.core.openid; + +import pro.gravit.launchserver.auth.core.User; + +import java.util.UUID; + +public interface UserStore { + User getByUsername(String username); + + User getUserByUUID(UUID uuid); + + void createOrUpdateUser(User user); +} diff --git a/props.gradle b/props.gradle index 6ac97aee..1694aeb1 100644 --- a/props.gradle +++ b/props.gradle @@ -14,6 +14,7 @@ verLog4j = '2.20.0' verMySQLConn = '8.3.0' verPostgreSQLConn = '42.7.1' + verH2Conn = '2.2.224' verProguard = '7.4.1' verLaunch4j = '3.50' } From 9bd65c797beaa104ef404825347cbaa9a4ceea03 Mon Sep 17 00:00:00 2001 From: Gravita <12893402+gravit0@users.noreply.github.com> Date: Thu, 25 Apr 2024 01:31:46 +0700 Subject: [PATCH 02/15] [REFACTOR] ClientProfileBuilder --- .../command/hash/DownloadClientCommand.java | 9 +- .../command/profiles/CloneProfileCommand.java | 9 +- .../command/profiles/SaveProfilesCommand.java | 1 - .../runtime/client/ClientLauncherProcess.java | 7 +- .../launcher/base/profiles/ClientProfile.java | 132 ++---- .../base/profiles/ClientProfileBuilder.java | 375 ++++++++++++------ .../actions/OptionalActionClassPath.java | 8 +- .../client/ClientLauncherEntryPoint.java | 7 +- .../main/java/pro/gravit/utils/Version.java | 4 +- build.gradle | 2 +- 10 files changed, 314 insertions(+), 240 deletions(-) diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/command/hash/DownloadClientCommand.java b/LaunchServer/src/main/java/pro/gravit/launchserver/command/hash/DownloadClientCommand.java index b2e28cd2..9da32e9c 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/command/hash/DownloadClientCommand.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/command/hash/DownloadClientCommand.java @@ -5,6 +5,7 @@ import org.apache.logging.log4j.Logger; import pro.gravit.launcher.base.Launcher; import pro.gravit.launcher.base.profiles.ClientProfile; +import pro.gravit.launcher.base.profiles.ClientProfileBuilder; import pro.gravit.launcher.base.profiles.ClientProfileVersions; import pro.gravit.launchserver.LaunchServer; import pro.gravit.launchserver.command.Command; @@ -61,9 +62,11 @@ public void invoke(String... args) throws IOException, CommandException { try { JsonElement clientJson = server.mirrorManager.jsonRequest(null, "GET", "clients/%s.json", versionName); clientProfile = Launcher.gsonManager.configGson.fromJson(clientJson, ClientProfile.class); - clientProfile.setTitle(dirName); - clientProfile.setDir(dirName); - clientProfile.setUUID(UUID.randomUUID()); + var builder = new ClientProfileBuilder(clientProfile); + builder.setTitle(dirName); + builder.setDir(dirName); + builder.setUuid(UUID.randomUUID()); + clientProfile = builder.createClientProfile(); if (clientProfile.getServers() != null) { ClientProfile.ServerProfile serverProfile = clientProfile.getDefaultServerProfile(); if (serverProfile != null) { diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/command/profiles/CloneProfileCommand.java b/LaunchServer/src/main/java/pro/gravit/launchserver/command/profiles/CloneProfileCommand.java index 43e54f85..e943aa05 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/command/profiles/CloneProfileCommand.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/command/profiles/CloneProfileCommand.java @@ -4,6 +4,7 @@ import org.apache.logging.log4j.Logger; import pro.gravit.launcher.base.Launcher; import pro.gravit.launcher.base.profiles.ClientProfile; +import pro.gravit.launcher.base.profiles.ClientProfileBuilder; import pro.gravit.launchserver.LaunchServer; import pro.gravit.launchserver.command.Command; import pro.gravit.utils.helper.IOHelper; @@ -44,8 +45,9 @@ public void invoke(String... args) throws Exception { try(Reader reader = IOHelper.newReader(profilePath)) { profile = Launcher.gsonManager.gson.fromJson(reader, ClientProfile.class); } - profile.setTitle(args[1]); - profile.setUUID(UUID.randomUUID()); + var builder = new ClientProfileBuilder(profile); + builder.setTitle(args[1]); + builder.setUuid(UUID.randomUUID()); if(profile.getServers().size() == 1) { profile.getServers().getFirst().name = args[1]; } @@ -61,7 +63,8 @@ public void invoke(String... args) throws Exception { } }); } - profile.setDir(args[1]); + builder.setDir(args[1]); + profile = builder.createClientProfile(); var targetPath = server.profilesDir.resolve(args[1].concat(".json")); try(Writer writer = IOHelper.newWriter(targetPath)) { Launcher.gsonManager.gson.toJson(profile, writer); diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/command/profiles/SaveProfilesCommand.java b/LaunchServer/src/main/java/pro/gravit/launchserver/command/profiles/SaveProfilesCommand.java index c0f0f5d0..7aba43a4 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/command/profiles/SaveProfilesCommand.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/command/profiles/SaveProfilesCommand.java @@ -23,7 +23,6 @@ public SaveProfilesCommand(LaunchServer server) { } public static void saveProfile(ClientProfile profile, Path path) throws IOException { - if (profile.getUUID() == null) profile.setUUID(UUID.randomUUID()); if (profile.getServers().isEmpty()) { ClientProfile.ServerProfile serverProfile = new ClientProfile.ServerProfile(); serverProfile.isDefault = true; diff --git a/Launcher/src/main/java/pro/gravit/launcher/runtime/client/ClientLauncherProcess.java b/Launcher/src/main/java/pro/gravit/launcher/runtime/client/ClientLauncherProcess.java index 4928f57c..aaf4c5be 100644 --- a/Launcher/src/main/java/pro/gravit/launcher/runtime/client/ClientLauncherProcess.java +++ b/Launcher/src/main/java/pro/gravit/launcher/runtime/client/ClientLauncherProcess.java @@ -109,14 +109,14 @@ public static String getPathSeparator() { private void applyClientProfile() { this.systemClassPath.add(IOHelper.getCodeSource(ClientLauncherEntryPoint.class).toAbsolutePath().toString()); - Collections.addAll(this.jvmArgs, this.params.profile.getJvmArgs()); + this.jvmArgs.addAll(this.params.profile.getJvmArgs()); for (OptionalAction a : this.params.actions) { if (a instanceof OptionalActionJvmArgs) { this.jvmArgs.addAll(((OptionalActionJvmArgs) a).args); } } this.systemEnv.put("JAVA_HOME", javaVersion.jvmDir.toString()); - Collections.addAll(this.systemClassPath, this.params.profile.getAlternativeClassPath()); + this.systemClassPath.addAll(this.params.profile.getAlternativeClassPath()); if (params.ram > 0) { this.jvmArgs.add("-Xmx" + params.ram + 'M'); } @@ -128,8 +128,6 @@ private void applyClientProfile() { this.params.oauthExpiredTime = Request.getTokenExpiredTime(); this.params.extendedTokens = Request.getExtendedTokens(); } - this.jvmModules.addAll(this.params.profile.getModules()); - this.jvmModulesPaths.addAll(this.params.profile.getModulePath()); LauncherEngine.modulesManager.invokeEvent(new ClientProcessBuilderCreateEvent(this)); } @@ -148,7 +146,6 @@ public void start(boolean pipeOutput) throws IOException, InterruptedException { processArgs.add("-javaagent:".concat(IOHelper.getCodeSource(ClientLauncherEntryPoint.class).toAbsolutePath().toString())); } else if (params.profile.getClassLoaderConfig() == ClientProfile.ClassLoaderConfig.SYSTEM_ARGS) { systemClassPath.addAll(ClientLauncherEntryPoint.resolveClassPath(new HashSet<>(), workDir, params.actions, params.profile) - .filter(x -> !params.profile.getModulePath().contains(workDir.relativize(x).toString())) .map(Path::toString) .toList()); } diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/base/profiles/ClientProfile.java b/LauncherAPI/src/main/java/pro/gravit/launcher/base/profiles/ClientProfile.java index 3c268cac..5d55896d 100644 --- a/LauncherAPI/src/main/java/pro/gravit/launcher/base/profiles/ClientProfile.java +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/base/profiles/ClientProfile.java @@ -41,8 +41,6 @@ public final class ClientProfile implements Comparable { @LauncherNetworkAPI private List updateExclusions; @LauncherNetworkAPI - private List updateShared; - @LauncherNetworkAPI private List updateVerify; @LauncherNetworkAPI private Set updateOptional; @@ -51,10 +49,6 @@ public final class ClientProfile implements Comparable { @LauncherNetworkAPI private List classPath; @LauncherNetworkAPI - private List modulePath = new ArrayList<>(); - @LauncherNetworkAPI - private List modules = new ArrayList<>(); - @LauncherNetworkAPI private List altClassPath; @LauncherNetworkAPI private List clientArgs; @@ -89,54 +83,37 @@ public final class ClientProfile implements Comparable { @LauncherNetworkAPI private LaunchOptions.ModuleConf moduleConf; - public ClientProfile() { - update = new ArrayList<>(); - updateExclusions = new ArrayList<>(); - updateShared = new ArrayList<>(); - updateVerify = new ArrayList<>(); - updateOptional = new HashSet<>(); - jvmArgs = new ArrayList<>(); - classPath = new ArrayList<>(); - modulePath = new ArrayList<>(); - altClassPath = new ArrayList<>(); - clientArgs = new ArrayList<>(); - compatClasses = new ArrayList<>(); - properties = new HashMap<>(); - servers = new ArrayList<>(1); - classLoaderConfig = ClassLoaderConfig.LAUNCHER; - flags = new ArrayList<>(); - } - - public ClientProfile(List update, List updateExclusions, List updateShared, List updateVerify, Set updateOptional, List jvmArgs, List classPath, List modulePath, List modules, List altClassPath, List clientArgs, List compatClasses, Map properties, List servers, ClassLoaderConfig classLoaderConfig, List flags, Version version, String assetIndex, String dir, String assetDir, int recommendJavaVersion, int minJavaVersion, int maxJavaVersion, ProfileDefaultSettings settings, int sortIndex, UUID uuid, String title, String info, String mainClass) { + public ClientProfile(String title, UUID uuid, Version version, String info, String dir, int sortIndex, String assetIndex, String assetDir, List update, List updateExclusions, List updateVerify, Set updateOptional, List jvmArgs, List classPath, List altClassPath, List clientArgs, List compatClasses, List loadNatives, Map properties, List servers, ClassLoaderConfig classLoaderConfig, List flags, int recommendJavaVersion, int minJavaVersion, int maxJavaVersion, ProfileDefaultSettings settings, boolean limited, String mainClass, String mainModule, LaunchOptions.ModuleConf moduleConf) { + this.title = title; + this.uuid = uuid; + this.version = version; + this.info = info; + this.dir = dir; + this.sortIndex = sortIndex; + this.assetIndex = assetIndex; + this.assetDir = assetDir; this.update = update; this.updateExclusions = updateExclusions; - this.updateShared = updateShared; this.updateVerify = updateVerify; this.updateOptional = updateOptional; this.jvmArgs = jvmArgs; this.classPath = classPath; - this.modulePath = modulePath; - this.modules = modules; this.altClassPath = altClassPath; this.clientArgs = clientArgs; this.compatClasses = compatClasses; + this.loadNatives = loadNatives; this.properties = properties; this.servers = servers; this.classLoaderConfig = classLoaderConfig; - this.version = version; - this.assetIndex = assetIndex; - this.dir = dir; - this.assetDir = assetDir; + this.flags = flags; this.recommendJavaVersion = recommendJavaVersion; this.minJavaVersion = minJavaVersion; this.maxJavaVersion = maxJavaVersion; this.settings = settings; - this.sortIndex = sortIndex; - this.uuid = uuid; - this.title = title; - this.info = info; + this.limited = limited; this.mainClass = mainClass; - this.flags = flags; + this.mainModule = mainModule; + this.moduleConf = moduleConf; } public ServerProfile getDefaultServerProfile() { @@ -159,34 +136,22 @@ public FileNameMatcher getAssetUpdateMatcher() { return getVersion().compareTo(ClientProfileVersions.MINECRAFT_1_7_10) >= 0 ? ASSET_MATCHER : null; } - public String[] getClassPath() { - return classPath.toArray(new String[0]); + public List getClassPath() { + return Collections.unmodifiableList(classPath); } - public List getModulePath() { - return Collections.unmodifiableList(modulePath); + public List getAlternativeClassPath() { + return Collections.unmodifiableList(altClassPath); } - public List getModules() { - return Collections.unmodifiableList(modules); - } - - public String[] getAlternativeClassPath() { - return altClassPath.toArray(new String[0]); - } - - public String[] getClientArgs() { - return clientArgs.toArray(new String[0]); + public List getClientArgs() { + return Collections.unmodifiableList(clientArgs); } public String getDir() { return dir; } - public void setDir(String dir) { - this.dir = dir; - } - public String getAssetDir() { return assetDir; } @@ -195,24 +160,25 @@ public List getUpdateExclusions() { return Collections.unmodifiableList(updateExclusions); } - public FileNameMatcher getClientUpdateMatcher(/*boolean excludeOptional*/) { + public List getUpdate() { + return Collections.unmodifiableList(update); + } + + public List getUpdateVerify() { + return Collections.unmodifiableList(updateVerify); + } + + public FileNameMatcher getClientUpdateMatcher() { String[] updateArray = update.toArray(new String[0]); String[] verifyArray = updateVerify.toArray(new String[0]); List excludeList; - //if(excludeOptional) - //{ - // excludeList = new ArrayList<>(); - // excludeList.addAll(updateExclusions); - // excludeList.addAll(updateOptional); - //} - //else excludeList = updateExclusions; String[] exclusionsArray = excludeList.toArray(new String[0]); return new FileNameMatcher(updateArray, verifyArray, exclusionsArray); } - public String[] getJvmArgs() { - return jvmArgs.toArray(new String[0]); + public List getJvmArgs() { + return Collections.unmodifiableList(jvmArgs); } public String getMainClass() { @@ -289,10 +255,6 @@ public OptionalFile getOptionalFile(String file) { return null; } - public Collection getShared() { - return updateShared; - } - public int getServerPort() { ServerProfile profile = getDefaultServerProfile(); return profile == null ? 25565 : profile.serverPort; @@ -306,26 +268,14 @@ public String getTitle() { return title; } - public void setTitle(String title) { - this.title = title; - } - public String getInfo() { return info; } - public void setInfo(String info) { - this.info = info; - } - public Version getVersion() { return version; } - public void setVersion(Version version) { - this.version = version; - } - @Deprecated public boolean isUpdateFastCheck() { return true; @@ -340,10 +290,6 @@ public UUID getUUID() { return uuid; } - public void setUUID(UUID uuid) { - this.uuid = uuid; - } - public boolean hasFlag(CompatibilityFlags flag) { return flags.contains(flag); } @@ -413,18 +359,6 @@ public String getProperty(String name) { return properties.get(name); } - public void putProperty(String name, String value) { - properties.put(name, value); - } - - public boolean containsProperty(String name) { - return properties.containsKey(name); - } - - public void clearProperties() { - properties.clear(); - } - public Map getProperties() { return Collections.unmodifiableMap(properties); } @@ -450,10 +384,6 @@ public ClassLoaderConfig getClassLoaderConfig() { return classLoaderConfig; } - public void setClassLoaderConfig(ClassLoaderConfig classLoaderConfig) { - this.classLoaderConfig = classLoaderConfig; - } - public boolean isLimited() { return limited; } diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/base/profiles/ClientProfileBuilder.java b/LauncherAPI/src/main/java/pro/gravit/launcher/base/profiles/ClientProfileBuilder.java index a518db5c..e13b59f1 100644 --- a/LauncherAPI/src/main/java/pro/gravit/launcher/base/profiles/ClientProfileBuilder.java +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/base/profiles/ClientProfileBuilder.java @@ -1,136 +1,112 @@ package pro.gravit.launcher.base.profiles; import pro.gravit.launcher.base.profiles.optional.OptionalFile; +import pro.gravit.utils.launch.LaunchOptions; import java.util.*; public class ClientProfileBuilder { - private List update = new ArrayList<>(); - private List updateExclusions = new ArrayList<>(); - private List updateShared = new ArrayList<>(); - private List updateVerify = new ArrayList<>(); - private Set updateOptional = new HashSet<>(); - private List jvmArgs = new ArrayList<>(); - private List classPath = new ArrayList<>(); - private List modulePath = new ArrayList<>(); - private List modules = new ArrayList<>(); - private List altClassPath = new ArrayList<>(); - private List clientArgs = new ArrayList<>(); - private List compatClasses = new ArrayList<>(); - private Map properties = new HashMap<>(); - private List servers = new ArrayList<>(); - private ClientProfile.ClassLoaderConfig classLoaderConfig = ClientProfile.ClassLoaderConfig.LAUNCHER; - private List flags = new ArrayList<>(); - private ClientProfile.Version version; - private String assetIndex; - private String dir; - private String assetDir; - private int recommendJavaVersion = 8; - private int minJavaVersion = 8; - private int maxJavaVersion = 999; - private ClientProfile.ProfileDefaultSettings settings = new ClientProfile.ProfileDefaultSettings(); - private int sortIndex; - private UUID uuid; private String title; + private UUID uuid; + private ClientProfile.Version version; private String info; + private String dir; + private int sortIndex; + private String assetIndex; + private String assetDir; + private List update; + private List updateExclusions; + private List updateVerify; + private Set updateOptional; + private List jvmArgs; + private List classPath; + private List altClassPath; + private List clientArgs; + private List compatClasses; + private List loadNatives; + private Map properties; + private List servers; + private ClientProfile.ClassLoaderConfig classLoaderConfig; + private List flags; + private int recommendJavaVersion; + private int minJavaVersion; + private int maxJavaVersion; + private ClientProfile.ProfileDefaultSettings settings; + private boolean limited; private String mainClass; + private String mainModule; + private LaunchOptions.ModuleConf moduleConf; - public void setUpdate(List update) { - this.update = update; + public ClientProfileBuilder() { + this.update = new ArrayList<>(); + this.updateExclusions = new ArrayList<>(); + this.updateVerify = new ArrayList<>(); + this.updateOptional = new HashSet<>(); + this.jvmArgs = new ArrayList<>(); + this.classPath = new ArrayList<>(); + this.altClassPath = new ArrayList<>(); + this.clientArgs = new ArrayList<>(); + this.compatClasses = new ArrayList<>(); + this.loadNatives = new ArrayList<>(); + this.properties = new HashMap<>(); + this.servers = new ArrayList<>(); + this.flags = new ArrayList<>(); } - public ClientProfileBuilder setUpdateExclusions(List updateExclusions) { - this.updateExclusions = updateExclusions; + public ClientProfileBuilder(ClientProfile profile) { + this.title = profile.getTitle(); + this.uuid = profile.getUUID(); + this.version = profile.getVersion(); + this.info = profile.getInfo(); + this.dir = profile.getDir(); + this.sortIndex = profile.getSortIndex(); + this.assetIndex = profile.getAssetIndex(); + this.assetDir = profile.getAssetDir(); + this.update = new ArrayList<>(profile.getUpdate()); + this.updateExclusions = new ArrayList<>(profile.getUpdateExclusions()); + this.updateVerify = new ArrayList<>(profile.getUpdateVerify()); + this.updateOptional = new HashSet<>(profile.getOptional()); + this.jvmArgs = new ArrayList<>(profile.getJvmArgs()); + this.classPath = new ArrayList<>(profile.getClassPath()); + this.altClassPath = new ArrayList<>(profile.getAlternativeClassPath()); + this.clientArgs = new ArrayList<>(profile.getClientArgs()); + this.compatClasses = new ArrayList<>(profile.getCompatClasses()); + this.loadNatives = new ArrayList<>(profile.getLoadNatives()); + this.properties = new HashMap<>(profile.getProperties()); + this.servers = new ArrayList<>(profile.getServers()); + this.flags = new ArrayList<>(profile.getFlags()); + this.recommendJavaVersion = profile.getRecommendJavaVersion(); + this.minJavaVersion = profile.getMinJavaVersion(); + this.maxJavaVersion = profile.getMaxJavaVersion(); + this.settings = profile.getSettings(); + this.limited = profile.isLimited(); + this.mainClass = profile.getMainClass(); + this.mainModule = profile.getMainModule(); + this.moduleConf = profile.getModuleConf(); + } + + public ClientProfileBuilder setTitle(String title) { + this.title = title; return this; } - public ClientProfileBuilder setUpdateShared(List updateShared) { - this.updateShared = updateShared; + public ClientProfileBuilder setUuid(UUID uuid) { + this.uuid = uuid; return this; } - public void setUpdateVerify(List updateVerify) { - this.updateVerify = updateVerify; - } - - public void setUpdateOptional(Set updateOptional) { - this.updateOptional = updateOptional; - } - - public void setJvmArgs(List jvmArgs) { - this.jvmArgs = jvmArgs; - } - - public void setClassPath(List classPath) { - this.classPath = classPath; - } - - public void setAltClassPath(List altClassPath) { - this.altClassPath = altClassPath; - } - - public void setClientArgs(List clientArgs) { - this.clientArgs = clientArgs; - } - - public ClientProfileBuilder setCompatClasses(List compatClasses) { - this.compatClasses = compatClasses; - return this; - } - - public ClientProfileBuilder setProperties(Map properties) { - this.properties = properties; - return this; - } - - public void setServers(List servers) { - this.servers = servers; - } - - public void setClassLoaderConfig(ClientProfile.ClassLoaderConfig classLoaderConfig) { - this.classLoaderConfig = classLoaderConfig; - } - - public void setVersion(ClientProfile.Version version) { + public ClientProfileBuilder setVersion(ClientProfile.Version version) { this.version = version; + return this; } - public void setAssetIndex(String assetIndex) { - this.assetIndex = assetIndex; + public ClientProfileBuilder setInfo(String info) { + this.info = info; + return this; } - public void setDir(String dir) { + public ClientProfileBuilder setDir(String dir) { this.dir = dir; - } - - public void setAssetDir(String assetDir) { - this.assetDir = assetDir; - } - - public void setRecommendJavaVersion(int recommendJavaVersion) { - this.recommendJavaVersion = recommendJavaVersion; - } - - public ClientProfileBuilder setModulePath(List modulePath) { - this.modulePath = modulePath; - return this; - } - - public ClientProfileBuilder setModules(List modules) { - this.modules = modules; - return this; - } - - public void setMinJavaVersion(int minJavaVersion) { - this.minJavaVersion = minJavaVersion; - } - - public void setMaxJavaVersion(int maxJavaVersion) { - this.maxJavaVersion = maxJavaVersion; - } - - public ClientProfileBuilder setSettings(ClientProfile.ProfileDefaultSettings settings) { - this.settings = settings; return this; } @@ -139,20 +115,140 @@ public ClientProfileBuilder setSortIndex(int sortIndex) { return this; } - public void setUuid(UUID uuid) { - this.uuid = uuid; + public ClientProfileBuilder setAssetIndex(String assetIndex) { + this.assetIndex = assetIndex; + return this; } - public void setTitle(String title) { - this.title = title; + public ClientProfileBuilder setAssetDir(String assetDir) { + this.assetDir = assetDir; + return this; } - public void setInfo(String info) { - this.info = info; + public ClientProfileBuilder setUpdate(List update) { + this.update = update; + return this; } - public void setMainClass(String mainClass) { - this.mainClass = mainClass; + public ClientProfileBuilder update(String value) { + this.update.add(value); + return this; + } + + public ClientProfileBuilder setUpdateExclusions(List updateExclusions) { + this.updateExclusions = updateExclusions; + return this; + } + + public ClientProfileBuilder updateExclusions(String value) { + this.updateExclusions.add(value); + return this; + } + + public ClientProfileBuilder setUpdateVerify(List updateVerify) { + this.updateVerify = updateVerify; + return this; + } + + public ClientProfileBuilder updateVerify(String value) { + this.updateVerify.add(value); + return this; + } + + public ClientProfileBuilder setUpdateOptional(Set updateOptional) { + this.updateOptional = updateOptional; + return this; + } + + public ClientProfileBuilder updateOptional(OptionalFile value) { + this.updateOptional.add(value); + return this; + } + + public ClientProfileBuilder setJvmArgs(List jvmArgs) { + this.jvmArgs = jvmArgs; + return this; + } + + public ClientProfileBuilder jvmArg(String value) { + this.jvmArgs.add(value); + return this; + } + + + public ClientProfileBuilder setClassPath(List classPath) { + this.classPath = classPath; + return this; + } + + public ClientProfileBuilder classPath(String value) { + this.classPath.add(value); + return this; + } + + public ClientProfileBuilder setAltClassPath(List altClassPath) { + this.altClassPath = altClassPath; + return this; + } + + public ClientProfileBuilder altClassPath(String value) { + this.altClassPath.add(value); + return this; + } + + public ClientProfileBuilder setClientArgs(List clientArgs) { + this.clientArgs = clientArgs; + return this; + } + + public ClientProfileBuilder clientArg(String value) { + this.clientArgs.add(value); + return this; + } + + public ClientProfileBuilder setCompatClasses(List compatClasses) { + this.compatClasses = compatClasses; + return this; + } + + public ClientProfileBuilder compatClass(String value) { + this.compatClasses.add(value); + return this; + } + + public ClientProfileBuilder setLoadNatives(List loadNatives) { + this.loadNatives = loadNatives; + return this; + } + + public ClientProfileBuilder loadNatives(String value) { + this.loadNatives.add(value); + return this; + } + + public ClientProfileBuilder setProperties(Map properties) { + this.properties = properties; + return this; + } + + public ClientProfileBuilder property(String name, String value) { + this.properties.put(name, value); + return this; + } + + public ClientProfileBuilder setServers(List servers) { + this.servers = servers; + return this; + } + + public ClientProfileBuilder server(ClientProfile.ServerProfile value) { + this.servers.add(value); + return this; + } + + public ClientProfileBuilder setClassLoaderConfig(ClientProfile.ClassLoaderConfig classLoaderConfig) { + this.classLoaderConfig = classLoaderConfig; + return this; } public ClientProfileBuilder setFlags(List flags) { @@ -160,7 +256,52 @@ public ClientProfileBuilder setFlags(List flag return this; } + public ClientProfileBuilder flag(ClientProfile.CompatibilityFlags value) { + this.flags.add(value); + return this; + } + + public ClientProfileBuilder setRecommendJavaVersion(int recommendJavaVersion) { + this.recommendJavaVersion = recommendJavaVersion; + return this; + } + + public ClientProfileBuilder setMinJavaVersion(int minJavaVersion) { + this.minJavaVersion = minJavaVersion; + return this; + } + + public ClientProfileBuilder setMaxJavaVersion(int maxJavaVersion) { + this.maxJavaVersion = maxJavaVersion; + return this; + } + + public ClientProfileBuilder setSettings(ClientProfile.ProfileDefaultSettings settings) { + this.settings = settings; + return this; + } + + public ClientProfileBuilder setLimited(boolean limited) { + this.limited = limited; + return this; + } + + public ClientProfileBuilder setMainClass(String mainClass) { + this.mainClass = mainClass; + return this; + } + + public ClientProfileBuilder setMainModule(String mainModule) { + this.mainModule = mainModule; + return this; + } + + public ClientProfileBuilder setModuleConf(LaunchOptions.ModuleConf moduleConf) { + this.moduleConf = moduleConf; + return this; + } + public ClientProfile createClientProfile() { - return new ClientProfile(update, updateExclusions, updateShared, updateVerify, updateOptional, jvmArgs, classPath, modulePath, modules, altClassPath, clientArgs, compatClasses, properties, servers, classLoaderConfig, flags, version, assetIndex, dir, assetDir, recommendJavaVersion, minJavaVersion, maxJavaVersion, settings, sortIndex, uuid, title, info, mainClass); + return new ClientProfile(title, uuid, version, info, dir, sortIndex, assetIndex, assetDir, update, updateExclusions, updateVerify, updateOptional, jvmArgs, classPath, altClassPath, clientArgs, compatClasses, loadNatives, properties, servers, classLoaderConfig, flags, recommendJavaVersion, minJavaVersion, maxJavaVersion, settings, limited, mainClass, mainModule, moduleConf); } } \ No newline at end of file diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/base/profiles/optional/actions/OptionalActionClassPath.java b/LauncherAPI/src/main/java/pro/gravit/launcher/base/profiles/optional/actions/OptionalActionClassPath.java index 51a09abf..af2c0675 100644 --- a/LauncherAPI/src/main/java/pro/gravit/launcher/base/profiles/optional/actions/OptionalActionClassPath.java +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/base/profiles/optional/actions/OptionalActionClassPath.java @@ -1,17 +1,19 @@ package pro.gravit.launcher.base.profiles.optional.actions; +import java.util.List; + public class OptionalActionClassPath extends OptionalAction { - public String[] args; + public List args; public boolean useAltClasspath = false; public OptionalActionClassPath() { } - public OptionalActionClassPath(String[] args) { + public OptionalActionClassPath(List args) { this.args = args; } - public OptionalActionClassPath(String[] args, boolean useAltClasspath) { + public OptionalActionClassPath(List args, boolean useAltClasspath) { this.args = args; this.useAltClasspath = useAltClasspath; } diff --git a/LauncherClient/src/main/java/pro/gravit/launcher/client/ClientLauncherEntryPoint.java b/LauncherClient/src/main/java/pro/gravit/launcher/client/ClientLauncherEntryPoint.java index eb476436..d084f9d5 100644 --- a/LauncherClient/src/main/java/pro/gravit/launcher/client/ClientLauncherEntryPoint.java +++ b/LauncherClient/src/main/java/pro/gravit/launcher/client/ClientLauncherEntryPoint.java @@ -120,7 +120,6 @@ private static void realMain(String[] args) throws Throwable { LogHelper.debug("Verifying ClientLauncher sign and classpath"); Set ignoredPath = new HashSet<>(); List classpath = resolveClassPath(ignoredPath, clientDir, params.actions, params.profile) - .filter(x -> !profile.getModulePath().contains(clientDir.relativize(x).toString())) .collect(Collectors.toCollection(ArrayList::new)); if(LogHelper.isDevEnabled()) { for(var e : classpath) { @@ -253,11 +252,11 @@ public static void verifyHDir(Path dir, HashedDir hdir, FileNameMatcher matcher, } } - private static LinkedList resolveClassPathList(Set ignorePaths, Path clientDir, String... classPath) throws IOException { + private static LinkedList resolveClassPathList(Set ignorePaths, Path clientDir, List classPath) throws IOException { return resolveClassPathStream(ignorePaths, clientDir, classPath).collect(Collectors.toCollection(LinkedList::new)); } - private static Stream resolveClassPathStream(Set ignorePaths, Path clientDir, String... classPath) throws IOException { + private static Stream resolveClassPathStream(Set ignorePaths, Path clientDir, List classPath) throws IOException { Stream.Builder builder = Stream.builder(); for (String classPathEntry : classPath) { Path path = clientDir.resolve(IOHelper.toPath(classPathEntry.replace(IOHelper.CROSS_SEPARATOR, IOHelper.PLATFORM_SEPARATOR))); @@ -301,7 +300,7 @@ private static void launch(ClientProfile profile, ClientParams params) throws Th params.addClientLegacyArgs(args); System.setProperty("minecraft.applet.TargetDirectory", params.clientDir); } - Collections.addAll(args, profile.getClientArgs()); + args.addAll(profile.getClientArgs()); for (OptionalAction action : params.actions) { if (action instanceof OptionalActionClientArgs) { args.addAll(((OptionalActionClientArgs) action).args); diff --git a/LauncherCore/src/main/java/pro/gravit/utils/Version.java b/LauncherCore/src/main/java/pro/gravit/utils/Version.java index ee50e0c1..4f32b9b9 100644 --- a/LauncherCore/src/main/java/pro/gravit/utils/Version.java +++ b/LauncherCore/src/main/java/pro/gravit/utils/Version.java @@ -6,9 +6,9 @@ public final class Version implements Comparable { public static final int MAJOR = 5; public static final int MINOR = 6; - public static final int PATCH = 1; + public static final int PATCH = 2; public static final int BUILD = 1; - public static final Version.Type RELEASE = Type.STABLE; + public static final Version.Type RELEASE = Type.DEV; public final int major; public final int minor; public final int patch; diff --git a/build.gradle b/build.gradle index 3e0cff99..1ca08833 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ id 'org.openjfx.javafxplugin' version '0.1.0' apply false } group = 'pro.gravit.launcher' -version = '5.6.1' +version = '5.6.2-SNAPSHOT' apply from: 'props.gradle' From 765f1a9d8f4fef5314418c08a497bbe1ecbf92b7 Mon Sep 17 00:00:00 2001 From: Gravita <12893402+gravit0@users.noreply.github.com> Date: Thu, 25 Apr 2024 02:06:44 +0700 Subject: [PATCH 03/15] [FEATURE] SQLCoreProvider --- .../launchserver/auth/core/AuthCoreProvider.java | 1 + .../launchserver/auth/core/SQLCoreProvider.java | 12 ++++++++++++ 2 files changed, 13 insertions(+) create mode 100644 LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/SQLCoreProvider.java diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/AuthCoreProvider.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/AuthCoreProvider.java index 806b657d..cef6f749 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/AuthCoreProvider.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/AuthCoreProvider.java @@ -55,6 +55,7 @@ public static void registerProviders() { providers.register("memory", MemoryAuthCoreProvider.class); providers.register("merge", MergeAuthCoreProvider.class); providers.register("openid", OpenIDAuthCoreProvider.class); + providers.register("sql", SQLCoreProvider.class); registredProviders = true; } } diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/SQLCoreProvider.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/SQLCoreProvider.java new file mode 100644 index 00000000..cff1ffd6 --- /dev/null +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/SQLCoreProvider.java @@ -0,0 +1,12 @@ +package pro.gravit.launchserver.auth.core; + +import pro.gravit.launchserver.auth.HikariSQLSourceConfig; +import pro.gravit.launchserver.auth.SQLSourceConfig; + +public class SQLCoreProvider extends AbstractSQLCoreProvider { + public HikariSQLSourceConfig holder; + @Override + public SQLSourceConfig getSQLConfig() { + return holder; + } +} From 095a5aef8b43dd64e7b2baa214b7ca31ea00a440 Mon Sep 17 00:00:00 2001 From: Gravita <12893402+gravit0@users.noreply.github.com> Date: Thu, 25 Apr 2024 02:09:17 +0700 Subject: [PATCH 04/15] [FEATURE] Add mariadb connector --- LaunchServer/build.gradle | 1 + props.gradle | 1 + 2 files changed, 2 insertions(+) diff --git a/LaunchServer/build.gradle b/LaunchServer/build.gradle index 44b75deb..2db95539 100644 --- a/LaunchServer/build.gradle +++ b/LaunchServer/build.gradle @@ -83,6 +83,7 @@ pack project(':LauncherAPI') bundle group: 'io.netty', name: 'netty-transport-native-epoll', version: rootProject['verNetty'], classifier: 'linux-x86_64' bundle group: 'org.slf4j', name: 'slf4j-api', version: rootProject['verSlf4j'] bundle group: 'com.mysql', name: 'mysql-connector-j', version: rootProject['verMySQLConn'] + bundle group: 'org.mariadb.jdbc', name: 'mariadb-java-client', version: rootProject['verMariaDBConn'] bundle group: 'org.postgresql', name: 'postgresql', version: rootProject['verPostgreSQLConn'] bundle group: 'com.h2database', name: 'h2', version: rootProject['verH2Conn'] bundle group: 'com.guardsquare', name: 'proguard-base', version: rootProject['verProguard'] diff --git a/props.gradle b/props.gradle index 1694aeb1..366c4453 100644 --- a/props.gradle +++ b/props.gradle @@ -13,6 +13,7 @@ verSlf4j = '2.0.9' verLog4j = '2.20.0' verMySQLConn = '8.3.0' + verMariaDBConn = '3.3.3' verPostgreSQLConn = '42.7.1' verH2Conn = '2.2.224' verProguard = '7.4.1' From 52c9196dcc9f460dfe6de03bcbedf4403dd56d98 Mon Sep 17 00:00:00 2001 From: Gravita <12893402+gravit0@users.noreply.github.com> Date: Thu, 25 Apr 2024 03:05:13 +0700 Subject: [PATCH 05/15] [FIX] SQLCoreProvider --- .../launchserver/auth/core/SQLCoreProvider.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/SQLCoreProvider.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/SQLCoreProvider.java index cff1ffd6..49161f85 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/SQLCoreProvider.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/SQLCoreProvider.java @@ -1,10 +1,25 @@ package pro.gravit.launchserver.auth.core; +import pro.gravit.launchserver.LaunchServer; +import pro.gravit.launchserver.auth.AuthProviderPair; import pro.gravit.launchserver.auth.HikariSQLSourceConfig; import pro.gravit.launchserver.auth.SQLSourceConfig; public class SQLCoreProvider extends AbstractSQLCoreProvider { public HikariSQLSourceConfig holder; + + @Override + public void close() { + super.close(); + holder.close(); + } + + @Override + public void init(LaunchServer server, AuthProviderPair pair) { + holder.init(); + super.init(server, pair); + } + @Override public SQLSourceConfig getSQLConfig() { return holder; From b5457ee8661c3a513f6570eed6e606f9226b5d91 Mon Sep 17 00:00:00 2001 From: XakepSDK Date: Thu, 25 Apr 2024 20:05:53 +0500 Subject: [PATCH 06/15] [FIX OpenID validate issuer and aud (#710) Co-authored-by: d3coder --- .../launchserver/auth/core/openid/OpenIDAuthenticator.java | 5 ++++- .../gravit/launchserver/auth/core/openid/OpenIDConfig.java | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/OpenIDAuthenticator.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/OpenIDAuthenticator.java index 5e0f9e0b..2500331d 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/OpenIDAuthenticator.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/OpenIDAuthenticator.java @@ -36,7 +36,10 @@ public class OpenIDAuthenticator { public OpenIDAuthenticator(OpenIDConfig openIDConfig) { this.openIDConfig = openIDConfig; var keyLocator = loadKeyLocator(openIDConfig); - this.jwtParser = Jwts.parser().keyLocator(keyLocator) + this.jwtParser = Jwts.parser() + .keyLocator(keyLocator) + .requireIssuer(openIDConfig.issuer()) + .requireAudience(openIDConfig.clientId()) .build(); } diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/OpenIDConfig.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/OpenIDConfig.java index 395f2046..2d4f3bae 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/OpenIDConfig.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/OpenIDConfig.java @@ -3,7 +3,8 @@ import java.net.URI; public record OpenIDConfig(URI tokenUri, String authorizationEndpoint, String clientId, String clientSecret, - String redirectUri, URI jwksUri, String scopes, ClaimExtractorConfig extractorConfig) { + String redirectUri, URI jwksUri, String scopes, String issuer, + ClaimExtractorConfig extractorConfig) { public record ClaimExtractorConfig(String usernameClaim, String uuidClaim) {} } From 6c0ead015b86f379bd13a00f2b30470995740c98 Mon Sep 17 00:00:00 2001 From: Gravita <12893402+gravit0@users.noreply.github.com> Date: Fri, 26 Apr 2024 01:49:09 +0700 Subject: [PATCH 07/15] [FIX] NPE in new profiles --- .../pro/gravit/launcher/base/profiles/ClientProfileBuilder.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/base/profiles/ClientProfileBuilder.java b/LauncherAPI/src/main/java/pro/gravit/launcher/base/profiles/ClientProfileBuilder.java index e13b59f1..667ba3f3 100644 --- a/LauncherAPI/src/main/java/pro/gravit/launcher/base/profiles/ClientProfileBuilder.java +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/base/profiles/ClientProfileBuilder.java @@ -51,6 +51,7 @@ public ClientProfileBuilder() { this.properties = new HashMap<>(); this.servers = new ArrayList<>(); this.flags = new ArrayList<>(); + this.settings = new ClientProfile.ProfileDefaultSettings(); } public ClientProfileBuilder(ClientProfile profile) { @@ -83,6 +84,7 @@ public ClientProfileBuilder(ClientProfile profile) { this.mainClass = profile.getMainClass(); this.mainModule = profile.getMainModule(); this.moduleConf = profile.getModuleConf(); + this.settings = profile.getSettings(); } public ClientProfileBuilder setTitle(String title) { From c9a81da60cf891e0f3df3352e87980984fb0a18f Mon Sep 17 00:00:00 2001 From: Gravita <12893402+gravit0@users.noreply.github.com> Date: Fri, 26 Apr 2024 02:01:50 +0700 Subject: [PATCH 08/15] [FIX] Profile generation --- .../gravit/launcher/base/profiles/ClientProfileBuilder.java | 5 ++++- .../gravit/launcher/base/profiles/ClientProfileVersions.java | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/base/profiles/ClientProfileBuilder.java b/LauncherAPI/src/main/java/pro/gravit/launcher/base/profiles/ClientProfileBuilder.java index 667ba3f3..3b156f50 100644 --- a/LauncherAPI/src/main/java/pro/gravit/launcher/base/profiles/ClientProfileBuilder.java +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/base/profiles/ClientProfileBuilder.java @@ -52,6 +52,10 @@ public ClientProfileBuilder() { this.servers = new ArrayList<>(); this.flags = new ArrayList<>(); this.settings = new ClientProfile.ProfileDefaultSettings(); + this.recommendJavaVersion = 21; + this.minJavaVersion = 17; + this.maxJavaVersion = 999; + this.classLoaderConfig = ClientProfile.ClassLoaderConfig.LAUNCHER; } public ClientProfileBuilder(ClientProfile profile) { @@ -84,7 +88,6 @@ public ClientProfileBuilder(ClientProfile profile) { this.mainClass = profile.getMainClass(); this.mainModule = profile.getMainModule(); this.moduleConf = profile.getModuleConf(); - this.settings = profile.getSettings(); } public ClientProfileBuilder setTitle(String title) { diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/base/profiles/ClientProfileVersions.java b/LauncherAPI/src/main/java/pro/gravit/launcher/base/profiles/ClientProfileVersions.java index 5d21aced..e2e15f6d 100644 --- a/LauncherAPI/src/main/java/pro/gravit/launcher/base/profiles/ClientProfileVersions.java +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/base/profiles/ClientProfileVersions.java @@ -18,4 +18,5 @@ private ClientProfileVersions() { public static final ClientProfile.Version MINECRAFT_1_20 = ClientProfile.Version.of("1.20"); public static final ClientProfile.Version MINECRAFT_1_20_2 = ClientProfile.Version.of("1.20.2"); public static final ClientProfile.Version MINECRAFT_1_20_3 = ClientProfile.Version.of("1.20.3"); + public static final ClientProfile.Version MINECRAFT_1_20_5 = ClientProfile.Version.of("1.20.5"); } From 7c637e078db955c531050088ef9762eeb167eb15 Mon Sep 17 00:00:00 2001 From: XakepSDK Date: Thu, 23 May 2024 22:42:32 +0500 Subject: [PATCH 09/15] [FIX] Fix OpenID access token validation (#712) Co-authored-by: d3coder --- .../launchserver/auth/core/openid/OpenIDAuthenticator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/OpenIDAuthenticator.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/OpenIDAuthenticator.java index 2500331d..cf34f59d 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/OpenIDAuthenticator.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/openid/OpenIDAuthenticator.java @@ -39,7 +39,7 @@ public OpenIDAuthenticator(OpenIDConfig openIDConfig) { this.jwtParser = Jwts.parser() .keyLocator(keyLocator) .requireIssuer(openIDConfig.issuer()) - .requireAudience(openIDConfig.clientId()) + .require("azp", openIDConfig.clientId()) .build(); } From 6a53891c6a44b8b623bc22352b940e602bfacf65 Mon Sep 17 00:00:00 2001 From: Gravita <12893402+gravit0@users.noreply.github.com> Date: Thu, 30 May 2024 22:28:23 +0700 Subject: [PATCH 10/15] [ANY] Update dependencies --- LaunchServer/build.gradle | 7 +++--- .../java/pro/gravit/launchserver/Main.java | 2 +- props.gradle | 25 +++++++++---------- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/LaunchServer/build.gradle b/LaunchServer/build.gradle index 2db95539..cc1b7a5c 100644 --- a/LaunchServer/build.gradle +++ b/LaunchServer/build.gradle @@ -70,13 +70,14 @@ dependencies { pack project(':LauncherAPI') - bundle group: 'me.tongfei', name: 'progressbar', version: '0.9.2' - bundle group: 'com.github.Marcono1234', name: 'gson-record-type-adapter-factory', version: 'v0.2.0' + bundle group: 'me.tongfei', name: 'progressbar', version: '0.10.1' + bundle group: 'com.github.Marcono1234', name: 'gson-record-type-adapter-factory', version: 'v0.3.0' bundle group: 'org.fusesource.jansi', name: 'jansi', version: rootProject['verJansi'] bundle group: 'org.jline', name: 'jline', version: rootProject['verJline'] bundle group: 'org.jline', name: 'jline-reader', version: rootProject['verJline'] bundle group: 'org.jline', name: 'jline-terminal', version: rootProject['verJline'] - bundle group: 'org.bouncycastle', name: 'bcpkix-jdk15on', version: rootProject['verBcpkix'] + bundle group: 'org.bouncycastle', name: 'bcprov-jdk18on', version: rootProject['verBcpkix'] + bundle group: 'org.bouncycastle', name: 'bcpkix-jdk15to18', version: rootProject['verBcpkix'] bundle group: 'org.ow2.asm', name: 'asm-commons', version: rootProject['verAsm'] bundle group: 'io.netty', name: 'netty-codec-http', version: rootProject['verNetty'] bundle group: 'io.netty', name: 'netty-transport-classes-epoll', version: rootProject['verNetty'] diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/Main.java b/LaunchServer/src/main/java/pro/gravit/launchserver/Main.java index fc95cb72..26cb56ca 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/Main.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/Main.java @@ -18,7 +18,7 @@ import java.util.stream.Stream; public class Main { - private static final List classpathOnly = List.of("proguard", "jline", "kotlin", "epoll"); + private static final List classpathOnly = List.of("proguard", "jline", "progressbar", "kotlin", "epoll"); private static final String LOG4J_PROPERTY = "log4j2.configurationFile"; private static boolean isClasspathOnly(Path path) { var fileName = path.getFileName().toString(); diff --git a/props.gradle b/props.gradle index 366c4453..61d2b3c4 100644 --- a/props.gradle +++ b/props.gradle @@ -1,21 +1,20 @@ project.ext { - verAsm = '9.6' - verNetty = '4.1.99.Final' - verOshiCore = '6.4.11' - verJunit = '5.9.3' + verAsm = '9.7' + verNetty = '4.1.110.Final' + verOshiCore = '6.6.1' + verJunit = '5.10.2' verGuavaC = '30.1.1-jre' verJansi = '2.4.1' - verJline = '3.25.0' + verJline = '3.26.1' verJwt = '0.12.5' verBcprov = '1.70' verGson = '2.10.1' - verBcpkix = '1.70' - verSlf4j = '2.0.9' - verLog4j = '2.20.0' - verMySQLConn = '8.3.0' - verMariaDBConn = '3.3.3' - verPostgreSQLConn = '42.7.1' + verBcpkix = '1.78.1' + verSlf4j = '2.0.13' + verLog4j = '2.23.1' + verMySQLConn = '8.4.0' + verMariaDBConn = '3.4.0' + verPostgreSQLConn = '42.7.3' verH2Conn = '2.2.224' - verProguard = '7.4.1' - verLaunch4j = '3.50' + verProguard = '7.5.0' } From 6a173b9b1bb379f10168935ff1285c9086a13d34 Mon Sep 17 00:00:00 2001 From: Gravita <12893402+gravit0@users.noreply.github.com> Date: Thu, 30 May 2024 22:35:27 +0700 Subject: [PATCH 11/15] [ANY] Update modules --- modules | 2 +- props.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules b/modules index dba18b58..13f51fa3 160000 --- a/modules +++ b/modules @@ -1 +1 @@ -Subproject commit dba18b58312a92e465ad17d78ea3504a8b3c1818 +Subproject commit 13f51fa3ac407d42cbbf33a0c0b88112e02050cb diff --git a/props.gradle b/props.gradle index 61d2b3c4..8b85574d 100644 --- a/props.gradle +++ b/props.gradle @@ -8,7 +8,7 @@ verJline = '3.26.1' verJwt = '0.12.5' verBcprov = '1.70' - verGson = '2.10.1' + verGson = '2.11.0' verBcpkix = '1.78.1' verSlf4j = '2.0.13' verLog4j = '2.23.1' From b84911d4459218e390b42037c565991ce96b9a9b Mon Sep 17 00:00:00 2001 From: Gravita <12893402+gravit0@users.noreply.github.com> Date: Thu, 30 May 2024 22:46:28 +0700 Subject: [PATCH 12/15] [ANY] Update modules --- modules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules b/modules index 13f51fa3..a52b9cc8 160000 --- a/modules +++ b/modules @@ -1 +1 @@ -Subproject commit 13f51fa3ac407d42cbbf33a0c0b88112e02050cb +Subproject commit a52b9cc8552445167b95e8933f4289bbaa70677d From 1d5044c24a07eb7014797ecf0afe361871a64431 Mon Sep 17 00:00:00 2001 From: Gravita <12893402+gravit0@users.noreply.github.com> Date: Fri, 31 May 2024 22:58:18 +0700 Subject: [PATCH 13/15] [FIX] Bouncy Castle cert gen --- LaunchServer/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/LaunchServer/build.gradle b/LaunchServer/build.gradle index cc1b7a5c..45f15d29 100644 --- a/LaunchServer/build.gradle +++ b/LaunchServer/build.gradle @@ -78,6 +78,7 @@ pack project(':LauncherAPI') bundle group: 'org.jline', name: 'jline-terminal', version: rootProject['verJline'] bundle group: 'org.bouncycastle', name: 'bcprov-jdk18on', version: rootProject['verBcpkix'] bundle group: 'org.bouncycastle', name: 'bcpkix-jdk15to18', version: rootProject['verBcpkix'] + bundle group: 'org.bouncycastle', name: 'bcutil-jdk18on', version: rootProject['verBcpkix'] bundle group: 'org.ow2.asm', name: 'asm-commons', version: rootProject['verAsm'] bundle group: 'io.netty', name: 'netty-codec-http', version: rootProject['verNetty'] bundle group: 'io.netty', name: 'netty-transport-classes-epoll', version: rootProject['verNetty'] From a4e5ef9d01b6a42c8590794dfd7defd6df146495 Mon Sep 17 00:00:00 2001 From: Gravita <12893402+gravit0@users.noreply.github.com> Date: Fri, 31 May 2024 23:30:19 +0700 Subject: [PATCH 14/15] [FIX] Bouncy Castle --- LaunchServer/build.gradle | 3 +-- .../src/main/java/pro/gravit/launchserver/Main.java | 9 +++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/LaunchServer/build.gradle b/LaunchServer/build.gradle index 45f15d29..fbf36cdc 100644 --- a/LaunchServer/build.gradle +++ b/LaunchServer/build.gradle @@ -77,8 +77,7 @@ pack project(':LauncherAPI') bundle group: 'org.jline', name: 'jline-reader', version: rootProject['verJline'] bundle group: 'org.jline', name: 'jline-terminal', version: rootProject['verJline'] bundle group: 'org.bouncycastle', name: 'bcprov-jdk18on', version: rootProject['verBcpkix'] - bundle group: 'org.bouncycastle', name: 'bcpkix-jdk15to18', version: rootProject['verBcpkix'] - bundle group: 'org.bouncycastle', name: 'bcutil-jdk18on', version: rootProject['verBcpkix'] + bundle group: 'org.bouncycastle', name: 'bcpkix-jdk18on', version: rootProject['verBcpkix'] bundle group: 'org.ow2.asm', name: 'asm-commons', version: rootProject['verAsm'] bundle group: 'io.netty', name: 'netty-codec-http', version: rootProject['verNetty'] bundle group: 'io.netty', name: 'netty-transport-classes-epoll', version: rootProject['verNetty'] diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/Main.java b/LaunchServer/src/main/java/pro/gravit/launchserver/Main.java index 26cb56ca..8ca8b467 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/Main.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/Main.java @@ -20,6 +20,7 @@ public class Main { private static final List classpathOnly = List.of("proguard", "jline", "progressbar", "kotlin", "epoll"); private static final String LOG4J_PROPERTY = "log4j2.configurationFile"; + private static final String DEBUG_PROPERTY = "launchserver.main.debug"; private static boolean isClasspathOnly(Path path) { var fileName = path.getFileName().toString(); for(var e : classpathOnly) { @@ -78,6 +79,14 @@ public static void main(String[] args) throws Throwable { ModuleLayer.Controller controller = (ModuleLayer.Controller) control.getJava9ModuleController(); LaunchServerControlHolder.setControl(control); LaunchServerControlHolder.setController(controller); + if(Boolean.getBoolean(DEBUG_PROPERTY)) { + for(var e : controller.layer().modules()) { + System.out.printf("Module %s\n", e.getName()); + for(var p : e.getPackages()) { + System.out.printf("Package %s\n", p); + } + } + } launch.launch("pro.gravit.launchserver.LaunchServerStarter", null, Arrays.asList(args)); } } From 5b8aa8cd5ed245fd3d957e8be6f3687c533c74ca Mon Sep 17 00:00:00 2001 From: Gravita <12893402+gravit0@users.noreply.github.com> Date: Fri, 31 May 2024 23:45:01 +0700 Subject: [PATCH 15/15] [ANY] 5.6.2-stable --- LauncherCore/src/main/java/pro/gravit/utils/Version.java | 2 +- build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/LauncherCore/src/main/java/pro/gravit/utils/Version.java b/LauncherCore/src/main/java/pro/gravit/utils/Version.java index 4f32b9b9..7356b3ec 100644 --- a/LauncherCore/src/main/java/pro/gravit/utils/Version.java +++ b/LauncherCore/src/main/java/pro/gravit/utils/Version.java @@ -8,7 +8,7 @@ public final class Version implements Comparable { public static final int MINOR = 6; public static final int PATCH = 2; public static final int BUILD = 1; - public static final Version.Type RELEASE = Type.DEV; + public static final Version.Type RELEASE = Type.STABLE; public final int major; public final int minor; public final int patch; diff --git a/build.gradle b/build.gradle index 1ca08833..211d7b5d 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ id 'org.openjfx.javafxplugin' version '0.1.0' apply false } group = 'pro.gravit.launcher' -version = '5.6.2-SNAPSHOT' +version = '5.6.2' apply from: 'props.gradle'