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():