Upload folder via GUI - src

This commit is contained in:
Git Manager GUI
2026-04-16 11:48:01 +02:00
parent 5e102ec4e1
commit 084172116d
13 changed files with 1377 additions and 142 deletions

View File

@@ -60,12 +60,36 @@ public class ApiHandler extends BaseHandler implements HttpHandler {
return;
}
// ── Archiv-Aktionen ──────────────────────────────────────────
if (path.startsWith("/api/archive/")) {
handleArchiveApi(ex, session, path, method);
return;
}
// ── FAQ-Aktionen ─────────────────────────────────────────────
if (path.startsWith("/api/faq")) {
handleFaqApi(ex, session, path, method);
return;
}
// ── Benutzer-Verwaltung ──────────────────────────────────────
if (path.startsWith("/api/users")) {
handleUsersApi(ex, session, path, method);
return;
}
// ── Backup ───────────────────────────────────────────────────
if (path.equals("/api/backup") && method.equals("POST")) {
if (!session.isAdmin()) { sendJson(ex, 403, err("Kein Zugriff")); return; }
java.io.File backup = plugin.getDatabaseManager().createBackup();
if (backup != null) {
sendJson(ex, 200, "{\"ok\":true,\"file\":\"" + jsonEsc(backup.getName()) + "\"}");
} else {
sendJson(ex, 500, err("Backup fehlgeschlagen"));
}
return;
}
sendJson(ex, 404, "{\"ok\":false,\"error\":\"Unbekannter Endpunkt\"}");
} catch (Exception e) {
@@ -287,6 +311,156 @@ public class ApiHandler extends BaseHandler implements HttpHandler {
sendJson(ex, 404, err("Unbekannter FAQ-Endpunkt"));
}
// ─────────────────────────── Archiv-API ────────────────────────────────
/**
* POST /api/archive/{id}/delete Ticket permanent löschen (admin only)
* POST /api/archive/{id}/restore Ticket wiederherstellen (admin only)
*/
private void handleArchiveApi(HttpExchange ex, WebSession session, String path, String method) throws IOException {
if (!session.canViewArchive()) { sendJson(ex, 403, err("Kein Zugriff")); return; }
if (!method.equals("POST")) { sendJson(ex, 405, err("Method not allowed")); return; }
// /api/archive/{id}/{action}
String[] parts = path.split("/");
if (parts.length < 5) { sendJson(ex, 400, err("Ungültiger Pfad")); return; }
int ticketId;
try { ticketId = Integer.parseInt(parts[3]); }
catch (NumberFormatException e) { sendJson(ex, 400, err("Ungültige ID")); return; }
String action = parts[4];
var db = plugin.getDatabaseManager();
switch (action) {
case "delete" -> {
if (!session.isAdmin()) { sendJson(ex, 403, err("Nur Admins dürfen löschen")); return; }
boolean ok = db.deleteArchivedTicket(ticketId);
sendJson(ex, ok ? 200 : 404, ok ? "{\"ok\":true}" : err("Ticket nicht gefunden"));
}
case "restore" -> {
if (!session.isAdmin()) { sendJson(ex, 403, err("Nur Admins dürfen wiederherstellen")); return; }
boolean ok = db.restoreArchivedTicket(ticketId);
sendJson(ex, ok ? 200 : 500, ok ? "{\"ok\":true}" : err("Wiederherstellen fehlgeschlagen"));
}
default -> sendJson(ex, 404, err("Unbekannte Archiv-Aktion: " + action));
}
}
// ─────────────────────────── Benutzer-API ──────────────────────────────
/**
* GET /api/users Alle Benutzer auflisten (admin only)
* POST /api/users Neuen Benutzer anlegen (admin only)
* body: {username, password, role}
* POST /api/users/{name}/password Passwort ändern (admin only)
* body: {password}
* DELETE /api/users/{name} Benutzer löschen (admin only)
*/
private void handleUsersApi(HttpExchange ex, WebSession session, String path, String method) throws IOException {
if (!session.isAdmin()) { sendJson(ex, 403, err("Kein Zugriff")); return; }
// GET /api/users Liste
if (path.equals("/api/users") && method.equals("GET")) {
org.bukkit.configuration.ConfigurationSection users =
plugin.getConfig().getConfigurationSection("web-panel.users");
StringBuilder json = new StringBuilder("[");
if (users != null) {
boolean first = true;
for (String key : users.getKeys(false)) {
if (!first) json.append(",");
first = false;
String role = plugin.getConfig().getString("web-panel.users." + key + ".role", "supporter");
json.append("{\"username\":\"").append(jsonEsc(key))
.append("\",\"role\":\"").append(jsonEsc(role)).append("\"}");
}
}
json.append("]");
sendJson(ex, 200, json.toString());
return;
}
// POST /api/users Anlegen
if (path.equals("/api/users") && method.equals("POST")) {
Map<String, String> body = parseJsonBody(ex);
String username = body.getOrDefault("username", "").trim();
String password = body.getOrDefault("password", "").trim();
String role = body.getOrDefault("role", "supporter").trim().toLowerCase();
if (username.isEmpty() || password.isEmpty()) {
sendJson(ex, 400, err("Benutzername und Passwort erforderlich")); return;
}
if (!role.equals("admin") && !role.equals("supporter") && !role.equals("archive_viewer")) {
sendJson(ex, 400, err("Ungültige Rolle (admin/supporter/archive_viewer)")); return;
}
// Prüfen ob Benutzer schon existiert
org.bukkit.configuration.ConfigurationSection existing =
plugin.getConfig().getConfigurationSection("web-panel.users");
if (existing != null) {
for (String k : existing.getKeys(false)) {
if (k.equalsIgnoreCase(username)) {
sendJson(ex, 409, err("Benutzer existiert bereits")); return;
}
}
}
String hash = de.ticketsystem.web.SessionManager.sha256(password);
plugin.getConfig().set("web-panel.users." + username + ".password-hash", hash);
plugin.getConfig().set("web-panel.users." + username + ".role", role);
plugin.saveConfig();
sendJson(ex, 200, "{\"ok\":true}");
return;
}
// POST /api/users/{name}/password Passwort ändern
if (path.matches("/api/users/[^/]+/password") && method.equals("POST")) {
String targetUser = path.split("/")[3];
Map<String, String> body = parseJsonBody(ex);
String newPass = body.getOrDefault("password", "").trim();
if (newPass.isEmpty()) { sendJson(ex, 400, err("Passwort darf nicht leer sein")); return; }
String cfgPath = findUserConfigPath(targetUser);
if (cfgPath == null) { sendJson(ex, 404, err("Benutzer nicht gefunden")); return; }
String hash = de.ticketsystem.web.SessionManager.sha256(newPass);
plugin.getConfig().set(cfgPath + ".password-hash", hash);
plugin.getConfig().set(cfgPath + ".password", null);
plugin.saveConfig();
// Alle Sessions dieses Benutzers invalidieren
sessionManager.invalidateUser(targetUser);
sendJson(ex, 200, "{\"ok\":true}");
return;
}
// DELETE /api/users/{name} Löschen
if (path.matches("/api/users/[^/]+") && method.equals("DELETE")) {
String targetUser = path.split("/")[3];
// Darf sich nicht selbst löschen
if (targetUser.equalsIgnoreCase(session.getUsername())) {
sendJson(ex, 400, err("Du kannst dich nicht selbst löschen")); return;
}
String cfgPath = findUserConfigPath(targetUser);
if (cfgPath == null) { sendJson(ex, 404, err("Benutzer nicht gefunden")); return; }
plugin.getConfig().set(cfgPath, null);
plugin.saveConfig();
sessionManager.invalidateUser(targetUser);
sendJson(ex, 200, "{\"ok\":true}");
return;
}
sendJson(ex, 404, err("Unbekannter Benutzer-Endpunkt"));
}
/** Sucht den config.yml-Pfad eines Benutzers (case-insensitiv). */
private String findUserConfigPath(String username) {
org.bukkit.configuration.ConfigurationSection users =
plugin.getConfig().getConfigurationSection("web-panel.users");
if (users == null) return null;
for (String key : users.getKeys(false)) {
if (key.equalsIgnoreCase(username)) return "web-panel.users." + key;
}
return null;
}
// ─────────────────────────── Hilfsmethoden ─────────────────────────────
/**