test penis
This commit is contained in:
@@ -13,6 +13,9 @@
|
||||
<maven.compiler.source>21</maven.compiler.source>
|
||||
<maven.compiler.target>21</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.organization.name>ZernMC</project.organization.name>
|
||||
<project.inceptionYear>2026</project.inceptionYear>
|
||||
<project.description>ZernMC Launcher - just a minimalistic launcher by SashegDev</project.description>
|
||||
<mainClass>me.sashegdev.zernmc.launcher.Main</mainClass>
|
||||
</properties>
|
||||
|
||||
|
||||
@@ -1,44 +1,40 @@
|
||||
package me.sashegdev.zernmc.launcher.auth;
|
||||
|
||||
import com.google.gson.*;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import me.sashegdev.zernmc.launcher.utils.Config;
|
||||
import me.sashegdev.zernmc.launcher.utils.ZAnsi;
|
||||
import me.sashegdev.zernmc.launcher.utils.ZHttpClient;
|
||||
|
||||
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.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
|
||||
public class AuthManager {
|
||||
|
||||
private static final Path AUTH_FILE = Config.getConfigDir().resolve("auth.json");
|
||||
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
|
||||
private static final HttpClient HTTP_CLIENT = HttpClient.newBuilder()
|
||||
.connectTimeout(Duration.ofSeconds(15))
|
||||
.build();
|
||||
|
||||
private static volatile AuthSession session = null;
|
||||
private static volatile UserInfo userInfo = null;
|
||||
|
||||
// === Роли (для совместимости) ===
|
||||
// === Роли ===
|
||||
public static final int ROLE_USER = 0;
|
||||
public static final int ROLE_PASS_HOLDER = 1;
|
||||
public static final int ROLE_MODERATOR = 2;
|
||||
public static final int ROLE_ELDER = 3;
|
||||
public static final int ROLE_CREATOR = 4;
|
||||
|
||||
// === Права доступа (синхронизировано с сервером) ===
|
||||
// === Права доступа ===
|
||||
public static final String PERM_VIEW_PACKS = "view_packs";
|
||||
public static final String PERM_DOWNLOAD_PACK = "download_pack";
|
||||
public static final String PERM_REQUEST_PASS = "request_pass";
|
||||
|
||||
public static boolean loadSavedSession() {
|
||||
if (!Files.exists(AUTH_FILE)) return false;
|
||||
@@ -48,10 +44,7 @@ public class AuthManager {
|
||||
if (loaded == null || loaded.accessToken == null) return false;
|
||||
|
||||
session = loaded;
|
||||
|
||||
if (session.username != null) {
|
||||
userInfo = fetchUserInfo();
|
||||
}
|
||||
userInfo = fetchUserInfo();
|
||||
|
||||
if (isAccessTokenExpired()) {
|
||||
return tryRefresh();
|
||||
@@ -62,6 +55,7 @@ public class AuthManager {
|
||||
}
|
||||
}
|
||||
|
||||
// ====================== АВТОРИЗАЦИЯ ======================
|
||||
public static AuthResult login(String username, String password) {
|
||||
return authRequest("/auth/login", username, password);
|
||||
}
|
||||
@@ -72,36 +66,22 @@ public class AuthManager {
|
||||
|
||||
private static AuthResult authRequest(String endpoint, String username, String password) {
|
||||
try {
|
||||
JsonObject body = new JsonObject();
|
||||
body.addProperty("username", username);
|
||||
body.addProperty("password", password);
|
||||
String body = GSON.toJson(new LoginRequest(username, password));
|
||||
SimpleHttpResponse resp = post(endpoint, body);
|
||||
|
||||
String jsonBody = GSON.toJson(body);
|
||||
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(URI.create(ZHttpClient.getBaseUrl() + endpoint))
|
||||
.timeout(Duration.ofSeconds(15))
|
||||
.header("Content-Type", "application/json")
|
||||
.header("Accept", "application/json")
|
||||
.header("User-Agent", "ZernMC-Launcher/1.0")
|
||||
.POST(HttpRequest.BodyPublishers.ofString(jsonBody, StandardCharsets.UTF_8))
|
||||
.build();
|
||||
|
||||
HttpResponse<String> response = HTTP_CLIENT.send(request, HttpResponse.BodyHandlers.ofString());
|
||||
|
||||
if (response.statusCode() == 200) {
|
||||
session = GSON.fromJson(response.body(), AuthSession.class);
|
||||
if (resp.statusCode() == 200) {
|
||||
session = GSON.fromJson(resp.body(), AuthSession.class);
|
||||
session.expiresAt = System.currentTimeMillis() / 1000L + session.expiresIn;
|
||||
saveSession();
|
||||
|
||||
userInfo = fetchUserInfo();
|
||||
|
||||
return AuthResult.ok();
|
||||
} else if (resp.statusCode() == 422) {
|
||||
return AuthResult.fail("Ошибка валидации: " + extractError(resp.body()));
|
||||
} else {
|
||||
String error = extractError(response.body());
|
||||
return AuthResult.fail(error);
|
||||
return AuthResult.fail(extractError(resp.body()));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return AuthResult.fail("Ошибка соединения: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
@@ -109,17 +89,7 @@ public class AuthManager {
|
||||
public static void logout() {
|
||||
if (session != null && session.refreshToken != null) {
|
||||
try {
|
||||
JsonObject body = new JsonObject();
|
||||
body.addProperty("refresh_token", session.refreshToken);
|
||||
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(URI.create(ZHttpClient.getBaseUrl() + "/auth/logout"))
|
||||
.timeout(Duration.ofSeconds(10))
|
||||
.header("Content-Type", "application/json")
|
||||
.POST(HttpRequest.BodyPublishers.ofString(GSON.toJson(body)))
|
||||
.build();
|
||||
|
||||
HTTP_CLIENT.send(request, HttpResponse.BodyHandlers.ofString());
|
||||
post("/auth/logout", "{\"refresh_token\":\"" + session.refreshToken + "\"}");
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
session = null;
|
||||
@@ -139,68 +109,12 @@ public class AuthManager {
|
||||
return session != null ? session.uuid : "00000000-0000-0000-0000-000000000000";
|
||||
}
|
||||
|
||||
public static int getRole() {
|
||||
return session != null ? session.role : ROLE_USER;
|
||||
}
|
||||
|
||||
public static String getRoleName() {
|
||||
return session != null ? session.roleName : "Игрок";
|
||||
}
|
||||
|
||||
// === Основные проверки ===
|
||||
public static boolean hasPass() {
|
||||
if (userInfo != null) return userInfo.has_pass;
|
||||
return getRole() >= ROLE_PASS_HOLDER;
|
||||
}
|
||||
|
||||
public static boolean hasPermission(String permission) {
|
||||
if (userInfo != null && userInfo.permissions != null) {
|
||||
return userInfo.permissions.contains(permission);
|
||||
}
|
||||
// Fallback на старую систему
|
||||
if (PERM_VIEW_PACKS.equals(permission) || PERM_DOWNLOAD_PACK.equals(permission)) {
|
||||
return hasPass();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean canViewPacks() {
|
||||
return hasPermission(PERM_VIEW_PACKS);
|
||||
}
|
||||
|
||||
public static boolean canDownloadPacks() {
|
||||
return hasPermission(PERM_DOWNLOAD_PACK);
|
||||
}
|
||||
|
||||
public static String getAccessToken() {
|
||||
if (session == null) return null;
|
||||
if (session == null) return "0";
|
||||
if (isAccessTokenExpired()) {
|
||||
tryRefresh();
|
||||
}
|
||||
return session != null ? session.accessToken : null;
|
||||
}
|
||||
|
||||
private static UserInfo fetchUserInfo() {
|
||||
if (!isLoggedIn()) return null;
|
||||
|
||||
try {
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(URI.create(ZHttpClient.getBaseUrl() + "/admin/me"))
|
||||
.timeout(Duration.ofSeconds(10))
|
||||
.header("Authorization", "Bearer " + session.accessToken)
|
||||
.header("Accept", "application/json")
|
||||
.GET()
|
||||
.build();
|
||||
|
||||
HttpResponse<String> response = HTTP_CLIENT.send(request, HttpResponse.BodyHandlers.ofString());
|
||||
|
||||
if (response.statusCode() == 200) {
|
||||
return GSON.fromJson(response.body(), UserInfo.class);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.err.println("Не удалось получить информацию о пользователе: " + e.getMessage());
|
||||
}
|
||||
return null;
|
||||
return session != null && session.accessToken != null ? session.accessToken : "0";
|
||||
}
|
||||
|
||||
private static boolean isAccessTokenExpired() {
|
||||
@@ -210,33 +124,19 @@ public class AuthManager {
|
||||
|
||||
private static boolean tryRefresh() {
|
||||
if (session == null || session.refreshToken == null) return false;
|
||||
|
||||
try {
|
||||
JsonObject body = new JsonObject();
|
||||
body.addProperty("refresh_token", session.refreshToken);
|
||||
String body = "{\"refresh_token\":\"" + session.refreshToken + "\"}";
|
||||
SimpleHttpResponse resp = post("/auth/refresh", body);
|
||||
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(URI.create(ZHttpClient.getBaseUrl() + "/auth/refresh"))
|
||||
.timeout(Duration.ofSeconds(15))
|
||||
.header("Content-Type", "application/json")
|
||||
.POST(HttpRequest.BodyPublishers.ofString(GSON.toJson(body)))
|
||||
.build();
|
||||
|
||||
HttpResponse<String> response = HTTP_CLIENT.send(request, HttpResponse.BodyHandlers.ofString());
|
||||
|
||||
if (response.statusCode() == 200) {
|
||||
JsonObject json = JsonParser.parseString(response.body()).getAsJsonObject();
|
||||
String newAccessToken = json.get("access_token").getAsString();
|
||||
int expiresIn = json.get("expires_in").getAsInt();
|
||||
|
||||
session.accessToken = newAccessToken;
|
||||
session.expiresAt = System.currentTimeMillis() / 1000L + expiresIn;
|
||||
if (resp.statusCode() == 200) {
|
||||
AuthSession newSession = GSON.fromJson(resp.body(), AuthSession.class);
|
||||
newSession.expiresAt = System.currentTimeMillis() / 1000L + newSession.expiresIn;
|
||||
session = newSession;
|
||||
userInfo = fetchUserInfo();
|
||||
saveSession();
|
||||
userInfo = fetchUserInfo(); // обновляем информацию после рефреша
|
||||
return true;
|
||||
}
|
||||
} catch (Exception ignored) {}
|
||||
|
||||
session = null;
|
||||
userInfo = null;
|
||||
try { Files.deleteIfExists(AUTH_FILE); } catch (Exception ignored) {}
|
||||
@@ -252,19 +152,122 @@ public class AuthManager {
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== ПОЛУЧЕНИЕ ИНФОРМАЦИИ О ПОЛЬЗОВАТЕЛЕ ====================
|
||||
private static UserInfo fetchUserInfo() {
|
||||
if (!isLoggedIn() || session.accessToken == null) return null;
|
||||
|
||||
try {
|
||||
// Используем существующий метод ZHttpClient.get() + вручную добавляем токен
|
||||
java.net.HttpURLConnection conn = null;
|
||||
try {
|
||||
URL url = new URL(ZHttpClient.getBaseUrl() + "/admin/me");
|
||||
conn = (java.net.HttpURLConnection) url.openConnection();
|
||||
conn.setRequestMethod("GET");
|
||||
conn.setRequestProperty("Accept", "application/json");
|
||||
conn.setRequestProperty("Authorization", "Bearer " + session.accessToken);
|
||||
conn.setConnectTimeout(10000);
|
||||
conn.setReadTimeout(10000);
|
||||
|
||||
int responseCode = conn.getResponseCode();
|
||||
if (responseCode != 200) return null;
|
||||
|
||||
StringBuilder response = new StringBuilder();
|
||||
try (var reader = new java.io.BufferedReader(
|
||||
new java.io.InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8))) {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
response.append(line);
|
||||
}
|
||||
}
|
||||
return GSON.fromJson(response.toString(), UserInfo.class);
|
||||
} finally {
|
||||
if (conn != null) conn.disconnect();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.err.println("Не удалось получить UserInfo: " + e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== ПРОВЕРКИ ПРАВ ====================
|
||||
public static boolean hasPass() {
|
||||
if (userInfo != null) return userInfo.has_pass;
|
||||
return getRole() >= ROLE_PASS_HOLDER;
|
||||
}
|
||||
|
||||
public static boolean canViewPacks() {
|
||||
if (userInfo != null && userInfo.permissions != null) {
|
||||
return userInfo.permissions.contains(PERM_VIEW_PACKS);
|
||||
}
|
||||
return hasPass(); // fallback для старых аккаунтов
|
||||
}
|
||||
|
||||
public static boolean canDownloadPacks() {
|
||||
if (userInfo != null && userInfo.permissions != null) {
|
||||
return userInfo.permissions.contains(PERM_DOWNLOAD_PACK);
|
||||
}
|
||||
return hasPass(); // fallback
|
||||
}
|
||||
|
||||
public static int getRole() {
|
||||
return session != null ? session.role : ROLE_USER;
|
||||
}
|
||||
|
||||
// ====================== POST ======================
|
||||
private static SimpleHttpResponse post(String endpoint, String jsonBody) throws Exception {
|
||||
String fullUrl = ZHttpClient.getBaseUrl() + endpoint;
|
||||
HttpURLConnection conn = null;
|
||||
|
||||
try {
|
||||
URL url = new URL(fullUrl);
|
||||
conn = (HttpURLConnection) url.openConnection();
|
||||
|
||||
conn.setRequestMethod("POST");
|
||||
conn.setRequestProperty("Content-Type", "application/json; charset=utf-8");
|
||||
conn.setRequestProperty("Accept", "application/json");
|
||||
conn.setRequestProperty("User-Agent", "ZernMC-Launcher/1.0");
|
||||
conn.setRequestProperty("Connection", "close");
|
||||
|
||||
if (session != null && session.accessToken != null) {
|
||||
conn.setRequestProperty("Authorization", "Bearer " + session.accessToken);
|
||||
}
|
||||
|
||||
conn.setDoOutput(true);
|
||||
conn.setConnectTimeout(15000);
|
||||
conn.setReadTimeout(15000);
|
||||
|
||||
byte[] input = jsonBody.getBytes(StandardCharsets.UTF_8);
|
||||
conn.setFixedLengthStreamingMode(input.length);
|
||||
|
||||
try (var os = conn.getOutputStream()) {
|
||||
os.write(input);
|
||||
os.flush();
|
||||
}
|
||||
|
||||
int statusCode = conn.getResponseCode();
|
||||
var is = (statusCode >= 200 && statusCode < 300) ? conn.getInputStream() : conn.getErrorStream();
|
||||
|
||||
String responseBody;
|
||||
try (var scanner = new java.util.Scanner(is, StandardCharsets.UTF_8.name())) {
|
||||
responseBody = scanner.useDelimiter("\\A").hasNext() ? scanner.next() : "";
|
||||
}
|
||||
|
||||
return new SimpleHttpResponse(statusCode, responseBody);
|
||||
|
||||
} finally {
|
||||
if (conn != null) conn.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
private static String extractError(String body) {
|
||||
try {
|
||||
JsonObject json = JsonParser.parseString(body).getAsJsonObject();
|
||||
if (json.has("detail")) {
|
||||
if (json.get("detail").isJsonArray()) {
|
||||
return json.getAsJsonArray("detail").get(0).getAsJsonObject()
|
||||
.get("msg").getAsString();
|
||||
return json.getAsJsonArray("detail").get(0).getAsJsonObject().get("msg").getAsString();
|
||||
}
|
||||
return json.get("detail").getAsString();
|
||||
}
|
||||
if (json.has("error")) {
|
||||
return json.get("error").getAsString();
|
||||
}
|
||||
} catch (Exception ignored) {}
|
||||
return body.length() > 200 ? body.substring(0, 200) + "..." : body;
|
||||
}
|
||||
@@ -278,7 +281,6 @@ public class AuthManager {
|
||||
public String username;
|
||||
public String uuid;
|
||||
public int role;
|
||||
@SerializedName("role_name") public String roleName;
|
||||
}
|
||||
|
||||
public static class UserInfo {
|
||||
@@ -287,13 +289,20 @@ public class AuthManager {
|
||||
public String uuid;
|
||||
public int role;
|
||||
public String role_name;
|
||||
public long created_at;
|
||||
public Long last_login;
|
||||
public boolean has_pass;
|
||||
public List<String> permissions;
|
||||
|
||||
public boolean hasPermission(String permission) {
|
||||
return permissions != null && permissions.contains(permission);
|
||||
public boolean hasPermission(String perm) {
|
||||
return permissions != null && permissions.contains(perm);
|
||||
}
|
||||
}
|
||||
|
||||
private static class LoginRequest {
|
||||
final String username;
|
||||
final String password;
|
||||
LoginRequest(String u, String p) {
|
||||
this.username = u;
|
||||
this.password = p;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -305,3 +314,17 @@ public class AuthManager {
|
||||
public static AuthResult fail(String msg) { return new AuthResult(false, msg); }
|
||||
}
|
||||
}
|
||||
|
||||
// ====================== ВСПОМОГАТЕЛЬНЫЙ КЛАСС ======================
|
||||
class SimpleHttpResponse {
|
||||
final int statusCode;
|
||||
final String body;
|
||||
|
||||
SimpleHttpResponse(int statusCode, String body) {
|
||||
this.statusCode = statusCode;
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
int statusCode() { return statusCode; }
|
||||
String body() { return body; }
|
||||
}
|
||||
Reference in New Issue
Block a user