diff --git a/README.md b/README.md index 22974d8..857a9fc 100644 --- a/README.md +++ b/README.md @@ -115,6 +115,8 @@ mvn clean package ### Благодарность Glitch135 - За бета-тест лаунчера и фидбеки + +### помощь Я был бы рад если нашлись люди кто мог бы помочь в разработке лаунчера и добавления к нему хотя бы базового UI чтоб было намногл удобнее работать с ним diff --git a/launcher/pom.xml b/launcher/pom.xml index 99887ba..e51e2fa 100644 --- a/launcher/pom.xml +++ b/launcher/pom.xml @@ -6,7 +6,7 @@ 4.0.0 me.sashegdev ZernMCLauncher - 1.0.6 + 1.0.7 jar diff --git a/launcher/src/main/java/me/sashegdev/zernmc/launcher/auth/AuthManager.java b/launcher/src/main/java/me/sashegdev/zernmc/launcher/auth/AuthManager.java index 6fd7fea..9304f02 100644 --- a/launcher/src/main/java/me/sashegdev/zernmc/launcher/auth/AuthManager.java +++ b/launcher/src/main/java/me/sashegdev/zernmc/launcher/auth/AuthManager.java @@ -2,6 +2,8 @@ package me.sashegdev.zernmc.launcher.auth; 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; @@ -141,16 +143,18 @@ public class AuthManager { private static String extractError(String body) { try { - int idx = body.indexOf("\"detail\""); - if (idx != -1) { - int s = body.indexOf("\"", idx + 9) + 1; - int e = body.indexOf("\"", s); - if (e > s) return body.substring(s, e); + JsonObject json = JsonParser.parseString(body).getAsJsonObject(); + if (json.has("detail")) { + return json.get("detail").getAsString(); + } + if (json.has("error")) { + return json.get("error").getAsString(); } } catch (Exception ignored) {} - return "Неизвестная ошибка"; + return body.length() > 200 ? body.substring(0, 200) + "..." : body; } + // ====================== ВНУТРЕННИЕ КЛАССЫ ====================== public static class AuthSession { diff --git a/server/auth.py b/server/auth.py index 5872ca8..1c61c82 100644 --- a/server/auth.py +++ b/server/auth.py @@ -80,7 +80,7 @@ def init_db(): last_login REAL ); - CREATE TABLE IF NOT EXISTS passes ( -- НОВАЯ ТАБЛИЦА + CREATE TABLE IF NOT EXISTS passes ( code TEXT PRIMARY KEY, -- ZERN-XXXXXX is_used BOOLEAN DEFAULT 0, activated_by INTEGER REFERENCES users(id), @@ -96,6 +96,13 @@ def init_db(): activated_at REAL NOT NULL, PRIMARY KEY (user_id, pass_code) ); + + CREATE TABLE IF NOT EXISTS refresh_tokens ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE, + token_hash TEXT NOT NULL, + expires_at REAL NOT NULL + ); """) conn.commit() conn.close() @@ -143,7 +150,7 @@ async def register(body: RegisterRequest, request: Request): conn = get_db() try: if conn.execute("SELECT 1 FROM users WHERE username = ? COLLATE NOCASE", (body.username,)).fetchone(): - raise HTTPException(409, "Имя пользователя уже занято") + raise HTTPException(status_code=409, detail="Имя пользователя уже занято") uuid = generate_uuid() pw_hash = hash_password(body.password) @@ -156,11 +163,20 @@ async def register(body: RegisterRequest, request: Request): user_id = conn.lastrowid conn.commit() - return _issue_tokens(conn, user_id, body.username, uuid) + # Вызываем функцию и явно преобразуем в dict, чтобы избежать проблем сериализации + tokens = _issue_tokens(conn, user_id, body.username, uuid) + return tokens.model_dump() if hasattr(tokens, "model_dump") else tokens + + except HTTPException: + raise + except Exception as e: + logger.error("Register error", exc_info=True) + raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}") finally: conn.close() + @router.post("/login", response_model=TokenResponse) async def login(body: LoginRequest, request: Request): conn = get_db() diff --git a/server/main.py b/server/main.py index cf9e0fa..c9e9df5 100644 --- a/server/main.py +++ b/server/main.py @@ -869,6 +869,15 @@ async def api_my_passes(request: Request): return {"passes": passes, "has_active": any(p["is_active"] for p in passes)} +@app.exception_handler(Exception) +async def global_exception_handler(request: Request, exc: Exception): + logger.error("Unhandled exception", exc_info=True) + return JSONResponse( + status_code=500, + content={"detail": "Internal Server Error", "type": type(exc).__name__} + ) + + # Cleanup on shutdown @app.on_event("shutdown") async def shutdown_proxy():