fixes
This commit is contained in:
@@ -28,13 +28,18 @@ public class AuthManager {
|
|||||||
private static volatile AuthSession session = null;
|
private static volatile AuthSession session = null;
|
||||||
private static volatile UserInfo userInfo = null;
|
private static volatile UserInfo userInfo = null;
|
||||||
|
|
||||||
// Роли
|
// === Роли (для совместимости) ===
|
||||||
public static final int ROLE_USER = 0;
|
public static final int ROLE_USER = 0;
|
||||||
public static final int ROLE_PASS_HOLDER = 1;
|
public static final int ROLE_PASS_HOLDER = 1;
|
||||||
public static final int ROLE_MODERATOR = 2;
|
public static final int ROLE_MODERATOR = 2;
|
||||||
public static final int ROLE_ELDER = 3;
|
public static final int ROLE_ELDER = 3;
|
||||||
public static final int ROLE_CREATOR = 4;
|
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() {
|
public static boolean loadSavedSession() {
|
||||||
if (!Files.exists(AUTH_FILE)) return false;
|
if (!Files.exists(AUTH_FILE)) return false;
|
||||||
try {
|
try {
|
||||||
@@ -43,12 +48,11 @@ public class AuthManager {
|
|||||||
if (loaded == null || loaded.accessToken == null) return false;
|
if (loaded == null || loaded.accessToken == null) return false;
|
||||||
|
|
||||||
session = loaded;
|
session = loaded;
|
||||||
|
|
||||||
// Получаем информацию о пользователе
|
|
||||||
if (session.username != null) {
|
if (session.username != null) {
|
||||||
userInfo = fetchUserInfo();
|
userInfo = fetchUserInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isAccessTokenExpired()) {
|
if (isAccessTokenExpired()) {
|
||||||
return tryRefresh();
|
return tryRefresh();
|
||||||
}
|
}
|
||||||
@@ -71,9 +75,9 @@ public class AuthManager {
|
|||||||
JsonObject body = new JsonObject();
|
JsonObject body = new JsonObject();
|
||||||
body.addProperty("username", username);
|
body.addProperty("username", username);
|
||||||
body.addProperty("password", password);
|
body.addProperty("password", password);
|
||||||
|
|
||||||
String jsonBody = GSON.toJson(body);
|
String jsonBody = GSON.toJson(body);
|
||||||
|
|
||||||
HttpRequest request = HttpRequest.newBuilder()
|
HttpRequest request = HttpRequest.newBuilder()
|
||||||
.uri(URI.create(ZHttpClient.getBaseUrl() + endpoint))
|
.uri(URI.create(ZHttpClient.getBaseUrl() + endpoint))
|
||||||
.timeout(Duration.ofSeconds(15))
|
.timeout(Duration.ofSeconds(15))
|
||||||
@@ -84,15 +88,14 @@ public class AuthManager {
|
|||||||
.build();
|
.build();
|
||||||
|
|
||||||
HttpResponse<String> response = HTTP_CLIENT.send(request, HttpResponse.BodyHandlers.ofString());
|
HttpResponse<String> response = HTTP_CLIENT.send(request, HttpResponse.BodyHandlers.ofString());
|
||||||
|
|
||||||
if (response.statusCode() == 200) {
|
if (response.statusCode() == 200) {
|
||||||
session = GSON.fromJson(response.body(), AuthSession.class);
|
session = GSON.fromJson(response.body(), AuthSession.class);
|
||||||
session.expiresAt = System.currentTimeMillis() / 1000L + session.expiresIn;
|
session.expiresAt = System.currentTimeMillis() / 1000L + session.expiresIn;
|
||||||
saveSession();
|
saveSession();
|
||||||
|
|
||||||
// Получаем информацию о пользователе
|
|
||||||
userInfo = fetchUserInfo();
|
userInfo = fetchUserInfo();
|
||||||
|
|
||||||
return AuthResult.ok();
|
return AuthResult.ok();
|
||||||
} else {
|
} else {
|
||||||
String error = extractError(response.body());
|
String error = extractError(response.body());
|
||||||
@@ -108,14 +111,14 @@ public class AuthManager {
|
|||||||
try {
|
try {
|
||||||
JsonObject body = new JsonObject();
|
JsonObject body = new JsonObject();
|
||||||
body.addProperty("refresh_token", session.refreshToken);
|
body.addProperty("refresh_token", session.refreshToken);
|
||||||
|
|
||||||
HttpRequest request = HttpRequest.newBuilder()
|
HttpRequest request = HttpRequest.newBuilder()
|
||||||
.uri(URI.create(ZHttpClient.getBaseUrl() + "/auth/logout"))
|
.uri(URI.create(ZHttpClient.getBaseUrl() + "/auth/logout"))
|
||||||
.timeout(Duration.ofSeconds(10))
|
.timeout(Duration.ofSeconds(10))
|
||||||
.header("Content-Type", "application/json")
|
.header("Content-Type", "application/json")
|
||||||
.POST(HttpRequest.BodyPublishers.ofString(GSON.toJson(body)))
|
.POST(HttpRequest.BodyPublishers.ofString(GSON.toJson(body)))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
HTTP_CLIENT.send(request, HttpResponse.BodyHandlers.ofString());
|
HTTP_CLIENT.send(request, HttpResponse.BodyHandlers.ofString());
|
||||||
} catch (Exception ignored) {}
|
} catch (Exception ignored) {}
|
||||||
}
|
}
|
||||||
@@ -144,20 +147,29 @@ public class AuthManager {
|
|||||||
return session != null ? session.roleName : "Игрок";
|
return session != null ? session.roleName : "Игрок";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// === Основные проверки ===
|
||||||
public static boolean hasPass() {
|
public static boolean hasPass() {
|
||||||
|
if (userInfo != null) return userInfo.has_pass;
|
||||||
return getRole() >= ROLE_PASS_HOLDER;
|
return getRole() >= ROLE_PASS_HOLDER;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isModerator() {
|
public static boolean hasPermission(String permission) {
|
||||||
return getRole() >= ROLE_MODERATOR;
|
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 isElder() {
|
public static boolean canViewPacks() {
|
||||||
return getRole() >= ROLE_ELDER;
|
return hasPermission(PERM_VIEW_PACKS);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isCreator() {
|
public static boolean canDownloadPacks() {
|
||||||
return getRole() == ROLE_CREATOR;
|
return hasPermission(PERM_DOWNLOAD_PACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getAccessToken() {
|
public static String getAccessToken() {
|
||||||
@@ -170,7 +182,7 @@ public class AuthManager {
|
|||||||
|
|
||||||
private static UserInfo fetchUserInfo() {
|
private static UserInfo fetchUserInfo() {
|
||||||
if (!isLoggedIn()) return null;
|
if (!isLoggedIn()) return null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
HttpRequest request = HttpRequest.newBuilder()
|
HttpRequest request = HttpRequest.newBuilder()
|
||||||
.uri(URI.create(ZHttpClient.getBaseUrl() + "/admin/me"))
|
.uri(URI.create(ZHttpClient.getBaseUrl() + "/admin/me"))
|
||||||
@@ -181,7 +193,7 @@ public class AuthManager {
|
|||||||
.build();
|
.build();
|
||||||
|
|
||||||
HttpResponse<String> response = HTTP_CLIENT.send(request, HttpResponse.BodyHandlers.ofString());
|
HttpResponse<String> response = HTTP_CLIENT.send(request, HttpResponse.BodyHandlers.ofString());
|
||||||
|
|
||||||
if (response.statusCode() == 200) {
|
if (response.statusCode() == 200) {
|
||||||
return GSON.fromJson(response.body(), UserInfo.class);
|
return GSON.fromJson(response.body(), UserInfo.class);
|
||||||
}
|
}
|
||||||
@@ -198,11 +210,11 @@ public class AuthManager {
|
|||||||
|
|
||||||
private static boolean tryRefresh() {
|
private static boolean tryRefresh() {
|
||||||
if (session == null || session.refreshToken == null) return false;
|
if (session == null || session.refreshToken == null) return false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
JsonObject body = new JsonObject();
|
JsonObject body = new JsonObject();
|
||||||
body.addProperty("refresh_token", session.refreshToken);
|
body.addProperty("refresh_token", session.refreshToken);
|
||||||
|
|
||||||
HttpRequest request = HttpRequest.newBuilder()
|
HttpRequest request = HttpRequest.newBuilder()
|
||||||
.uri(URI.create(ZHttpClient.getBaseUrl() + "/auth/refresh"))
|
.uri(URI.create(ZHttpClient.getBaseUrl() + "/auth/refresh"))
|
||||||
.timeout(Duration.ofSeconds(15))
|
.timeout(Duration.ofSeconds(15))
|
||||||
@@ -211,19 +223,20 @@ public class AuthManager {
|
|||||||
.build();
|
.build();
|
||||||
|
|
||||||
HttpResponse<String> response = HTTP_CLIENT.send(request, HttpResponse.BodyHandlers.ofString());
|
HttpResponse<String> response = HTTP_CLIENT.send(request, HttpResponse.BodyHandlers.ofString());
|
||||||
|
|
||||||
if (response.statusCode() == 200) {
|
if (response.statusCode() == 200) {
|
||||||
JsonObject json = JsonParser.parseString(response.body()).getAsJsonObject();
|
JsonObject json = JsonParser.parseString(response.body()).getAsJsonObject();
|
||||||
String newAccessToken = json.get("access_token").getAsString();
|
String newAccessToken = json.get("access_token").getAsString();
|
||||||
int expiresIn = json.get("expires_in").getAsInt();
|
int expiresIn = json.get("expires_in").getAsInt();
|
||||||
|
|
||||||
session.accessToken = newAccessToken;
|
session.accessToken = newAccessToken;
|
||||||
session.expiresAt = System.currentTimeMillis() / 1000L + expiresIn;
|
session.expiresAt = System.currentTimeMillis() / 1000L + expiresIn;
|
||||||
saveSession();
|
saveSession();
|
||||||
|
userInfo = fetchUserInfo(); // обновляем информацию после рефреша
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} catch (Exception ignored) {}
|
} catch (Exception ignored) {}
|
||||||
|
|
||||||
session = null;
|
session = null;
|
||||||
userInfo = null;
|
userInfo = null;
|
||||||
try { Files.deleteIfExists(AUTH_FILE); } catch (Exception ignored) {}
|
try { Files.deleteIfExists(AUTH_FILE); } catch (Exception ignored) {}
|
||||||
@@ -242,7 +255,6 @@ public class AuthManager {
|
|||||||
private static String extractError(String body) {
|
private static String extractError(String body) {
|
||||||
try {
|
try {
|
||||||
JsonObject json = JsonParser.parseString(body).getAsJsonObject();
|
JsonObject json = JsonParser.parseString(body).getAsJsonObject();
|
||||||
|
|
||||||
if (json.has("detail")) {
|
if (json.has("detail")) {
|
||||||
if (json.get("detail").isJsonArray()) {
|
if (json.get("detail").isJsonArray()) {
|
||||||
return json.getAsJsonArray("detail").get(0).getAsJsonObject()
|
return json.getAsJsonArray("detail").get(0).getAsJsonObject()
|
||||||
@@ -254,12 +266,10 @@ public class AuthManager {
|
|||||||
return json.get("error").getAsString();
|
return json.get("error").getAsString();
|
||||||
}
|
}
|
||||||
} catch (Exception ignored) {}
|
} catch (Exception ignored) {}
|
||||||
|
|
||||||
return body.length() > 200 ? body.substring(0, 200) + "..." : body;
|
return body.length() > 200 ? body.substring(0, 200) + "..." : body;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ====================== ВНУТРЕННИЕ КЛАССЫ ======================
|
// ====================== ВНУТРЕННИЕ КЛАССЫ ======================
|
||||||
|
|
||||||
public static class AuthSession {
|
public static class AuthSession {
|
||||||
@SerializedName("access_token") public String accessToken;
|
@SerializedName("access_token") public String accessToken;
|
||||||
@SerializedName("refresh_token") public String refreshToken;
|
@SerializedName("refresh_token") public String refreshToken;
|
||||||
@@ -281,6 +291,10 @@ public class AuthManager {
|
|||||||
public Long last_login;
|
public Long last_login;
|
||||||
public boolean has_pass;
|
public boolean has_pass;
|
||||||
public List<String> permissions;
|
public List<String> permissions;
|
||||||
|
|
||||||
|
public boolean hasPermission(String permission) {
|
||||||
|
return permissions != null && permissions.contains(permission);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class AuthResult {
|
public static class AuthResult {
|
||||||
|
|||||||
@@ -81,13 +81,10 @@ public class LaunchMenu {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void installServerPack() throws Exception {
|
private void installServerPack() throws Exception {
|
||||||
// Проверяем наличие проходки
|
if (!AuthManager.canDownloadPacks()) {
|
||||||
if (!AuthManager.hasPass()) {
|
|
||||||
ConsoleUtils.clearScreen();
|
ConsoleUtils.clearScreen();
|
||||||
System.out.println(ZAnsi.brightRed("У вас нет активной проходки!"));
|
System.out.println(ZAnsi.brightRed("У вас нет права на скачивание сборок!"));
|
||||||
System.out.println(ZAnsi.white("Чтобы скачивать сборки с сервера ZernMC, необходимо активировать проходку."));
|
System.out.println(ZAnsi.white("Для доступа к серверным сборкам необходима активная проходка."));
|
||||||
System.out.println();
|
|
||||||
System.out.println(ZAnsi.white("Обратитесь к администратору для получения проходки."));
|
|
||||||
ConsoleUtils.pause();
|
ConsoleUtils.pause();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -514,7 +511,7 @@ public class LaunchMenu {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void launchExistingInstance(Instance instance) {
|
private void launchExistingInstance(Instance instance) {
|
||||||
if (instance.isServerPack() && !AuthManager.hasPass()) {
|
if (instance.isServerPack() && !AuthManager.canDownloadPacks()) {
|
||||||
ConsoleUtils.clearScreen();
|
ConsoleUtils.clearScreen();
|
||||||
System.out.println(ZAnsi.brightRed("Для запуска серверной сборки требуется активная проходка!"));
|
System.out.println(ZAnsi.brightRed("Для запуска серверной сборки требуется активная проходка!"));
|
||||||
ConsoleUtils.pause();
|
ConsoleUtils.pause();
|
||||||
|
|||||||
@@ -43,6 +43,9 @@ public class PackDownloader {
|
|||||||
if (accessToken == null) {
|
if (accessToken == null) {
|
||||||
throw new IOException("Не авторизован. Требуется проходка для просмотра сборок.");
|
throw new IOException("Не авторизован. Требуется проходка для просмотра сборок.");
|
||||||
}
|
}
|
||||||
|
if (!AuthManager.canViewPacks()) {
|
||||||
|
throw new IOException("Для просмотра сборок требуется активная проходка");
|
||||||
|
}
|
||||||
|
|
||||||
// Используем HttpURLConnection для GET с авторизацией
|
// Используем HttpURLConnection для GET с авторизацией
|
||||||
java.net.HttpURLConnection connection = null;
|
java.net.HttpURLConnection connection = null;
|
||||||
@@ -90,11 +93,11 @@ public class PackDownloader {
|
|||||||
|
|
||||||
for (JsonElement elem : packsArray) {
|
for (JsonElement elem : packsArray) {
|
||||||
JsonObject pack = elem.getAsJsonObject();
|
JsonObject pack = elem.getAsJsonObject();
|
||||||
|
|
||||||
if (pack.has("error") || (pack.has("status") && "not_scanned".equals(pack.get("status").getAsString()))) {
|
if (pack.has("error") || (pack.has("status") && "not_scanned".equals(pack.get("status").getAsString()))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String name = pack.get("name").getAsString();
|
String name = pack.get("name").getAsString();
|
||||||
int version = pack.has("version") ? pack.get("version").getAsInt() : 0;
|
int version = pack.has("version") ? pack.get("version").getAsInt() : 0;
|
||||||
@@ -103,7 +106,7 @@ public class PackDownloader {
|
|||||||
String loaderVersion = pack.has("loader_version") && !pack.get("loader_version").isJsonNull()
|
String loaderVersion = pack.has("loader_version") && !pack.get("loader_version").isJsonNull()
|
||||||
? pack.get("loader_version").getAsString() : "";
|
? pack.get("loader_version").getAsString() : "";
|
||||||
int filesCount = pack.has("files_count") ? pack.get("files_count").getAsInt() : 0;
|
int filesCount = pack.has("files_count") ? pack.get("files_count").getAsInt() : 0;
|
||||||
|
|
||||||
LocalDateTime updatedAt = null;
|
LocalDateTime updatedAt = null;
|
||||||
if (pack.has("updated_at") && !pack.get("updated_at").isJsonNull()) {
|
if (pack.has("updated_at") && !pack.get("updated_at").isJsonNull()) {
|
||||||
try {
|
try {
|
||||||
@@ -111,14 +114,14 @@ public class PackDownloader {
|
|||||||
DateTimeFormatter.ISO_DATE_TIME);
|
DateTimeFormatter.ISO_DATE_TIME);
|
||||||
} catch (Exception ignored) {}
|
} catch (Exception ignored) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
result.add(new ServerPack(name, version, minecraftVersion, loaderType,
|
result.add(new ServerPack(name, version, minecraftVersion, loaderType,
|
||||||
loaderVersion, updatedAt, filesCount));
|
loaderVersion, updatedAt, filesCount));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
System.err.println("Ошибка парсинга пака: " + e.getMessage());
|
System.err.println("Ошибка парсинга пака: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -313,6 +316,9 @@ public class PackDownloader {
|
|||||||
if (accessToken == null) {
|
if (accessToken == null) {
|
||||||
throw new IOException("Не авторизован. Требуется проходка для скачивания сборок.");
|
throw new IOException("Не авторизован. Требуется проходка для скачивания сборок.");
|
||||||
}
|
}
|
||||||
|
if (!AuthManager.canDownloadPacks()) {
|
||||||
|
throw new IOException("Для скачивания сборок требуется активная проходка");
|
||||||
|
}
|
||||||
|
|
||||||
String url = ZHttpClient.getBaseUrl() + "/pack/" + packName + "/diff";
|
String url = ZHttpClient.getBaseUrl() + "/pack/" + packName + "/diff";
|
||||||
|
|
||||||
@@ -508,17 +514,6 @@ public class PackDownloader {
|
|||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Парсинг даты из строки
|
|
||||||
*/
|
|
||||||
private LocalDateTime parseDateTime(String dateTimeStr) {
|
|
||||||
try {
|
|
||||||
return LocalDateTime.parse(dateTimeStr, DATE_FORMATTER);
|
|
||||||
} catch (Exception e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ====================== Вложенные классы ======================
|
// ====================== Вложенные классы ======================
|
||||||
|
|
||||||
public static class PackManifest {
|
public static class PackManifest {
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@ import base64
|
|||||||
from fastapi.responses import StreamingResponse
|
from fastapi.responses import StreamingResponse
|
||||||
|
|
||||||
from auth import get_current_user, router as auth_router, init_db, verify_jwt
|
from auth import get_current_user, router as auth_router, init_db, verify_jwt
|
||||||
from server.roles import Permissions, has_permission
|
from roles import Permissions, has_permission
|
||||||
|
|
||||||
logger = structlog.get_logger(__name__)
|
logger = structlog.get_logger(__name__)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user