From 15d1c70b8cbdcd68aef55a102a71349597e13582 Mon Sep 17 00:00:00 2001 From: jannis Date: Thu, 29 Oct 2026 21:16:51 +0100 Subject: [PATCH] update --- .../eu/mhsl/craftattack/loginServer/Api.java | 114 +++++++++--------- .../mhsl/craftattack/loginServer/Dialog.java | 15 --- .../craftattack/loginServer/DialogState.java | 19 +-- .../loginServer/PlayerHandler.java | 54 +++++++-- src/main/resources/config.yml | 4 +- 5 files changed, 105 insertions(+), 101 deletions(-) diff --git a/src/main/java/eu/mhsl/craftattack/loginServer/Api.java b/src/main/java/eu/mhsl/craftattack/loginServer/Api.java index fb4f75e..63f50d2 100644 --- a/src/main/java/eu/mhsl/craftattack/loginServer/Api.java +++ b/src/main/java/eu/mhsl/craftattack/loginServer/Api.java @@ -1,18 +1,17 @@ package eu.mhsl.craftattack.loginServer; -import com.google.gson.JsonArray; +import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import java.io.IOException; import java.net.URI; -import java.net.URLEncoder; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.nio.charset.StandardCharsets; import java.time.Duration; -import java.util.Optional; +import java.util.Base64; import java.util.UUID; public final class Api { @@ -20,67 +19,78 @@ public final class Api { private Api() {} - public static void setProfile(UUID uuid, String username, String name, String secondName, String birthday, String phoneNumber) { - JsonObject body = new JsonObject(); - body.addProperty("uuid", uuid.toString()); - body.addProperty("username", username); - body.addProperty("name", name); - body.addProperty("secondName", secondName); - body.addProperty("birthday", birthday); - body.addProperty("phoneNumber", phoneNumber); - - send("POST", "players", "", body); - } - public static boolean isRegistered(UUID uuid) { - return find("players", "uuid", uuid.toString()).isPresent(); + HttpResponse response = call("GET", "/api/users/" + uuid, null, true); + int status = response.statusCode(); + if (status == 200) return true; + if (status == 404) return false; + throw new IllegalStateException("API-Fehler " + status + ": " + response.body()); } - public static boolean isSecretValid(String username, String secret) { - return find("secrets", "player", username, "secret", secret).isPresent(); - } - - private static Optional find(String collection, String... fieldValuePairs) { - StringBuilder filter = new StringBuilder(); - for (int i = 0; i < fieldValuePairs.length; i += 2) { - if (i > 0) filter.append(" && "); - String escaped = fieldValuePairs[i + 1].replace("\\", "\\\\").replace("'", "\\'"); - filter.append(fieldValuePairs[i]).append("='").append(escaped).append("'"); + public static final class SignupError extends RuntimeException { + public final String code; + public SignupError(String code, String message) { + super(message); + this.code = code; } - - String query = "?perPage=1&filter=" + URLEncoder.encode(filter.toString(), StandardCharsets.UTF_8); - JsonObject response = send("GET", collection, query, null); - if (!response.has("items")) return Optional.empty(); - JsonArray items = response.getAsJsonArray("items"); - return items.isEmpty() ? Optional.empty() : Optional.of(items.get(0).getAsJsonObject()); } - private static JsonObject send(String method, String collection, String path, JsonObject body) { - JsonObject login = new JsonObject(); - login.addProperty("identity", config("email")); - login.addProperty("password", config("password")); + public static void signup( + String firstname, + String lastname, + String birthdayIso, + String phone, + String username, + UUID uuid, + String edition + ) { + JsonObject body = new JsonObject(); + body.addProperty("firstname", firstname); + body.addProperty("lastname", lastname); + body.addProperty("birthday", birthdayIso); + body.addProperty("phone", phone); + body.addProperty("username", username); + body.addProperty("uuid", uuid.toString()); + body.addProperty("edition", edition); - String token = call("POST", "/api/collections/_superusers/auth-with-password", login, null) - .get("token").getAsString(); - return call(method, "/api/collections/" + collection + "/records" + path, body, token); + HttpResponse response = call("POST", "/api/users", body.toString(), true); + int status = response.statusCode(); + if (status >= 200 && status < 300) return; + + String code = switch (status) { + case 400 -> "BAD_REQUEST"; + case 401 -> "UNAUTHORIZED"; + case 409 -> "CONFLICT"; + default -> "UNKNOWN"; + }; + String message = response.body(); + try { + JsonObject json = JsonParser.parseString(response.body()).getAsJsonObject(); + JsonElement error = json.get("error"); + if (error != null && error.isJsonPrimitive()) message = error.getAsString(); + } catch (RuntimeException ignored) {} + throw new SignupError(code, "Signup fehlgeschlagen (" + status + "/" + code + "): " + message); } - private static JsonObject call(String method, String path, JsonObject body, String token) { + private static HttpResponse call(String method, String path, String body, boolean withAuth) { try { HttpRequest.Builder builder = HttpRequest.newBuilder(URI.create(config("url") + path)) .timeout(Duration.ofSeconds(5)) .header("Content-Type", "application/json") .method(method, body == null ? HttpRequest.BodyPublishers.noBody() - : HttpRequest.BodyPublishers.ofString(body.toString())); - if (token != null) builder.header("Authorization", token); + : HttpRequest.BodyPublishers.ofString(body)); - HttpResponse response = client.send(builder.build(), HttpResponse.BodyHandlers.ofString()); - if (response.statusCode() >= 300) { - throw new IllegalStateException("API-Fehler " + response.statusCode() + ": " + response.body()); + if (withAuth) { + String secret = config("secret"); + if (!secret.isBlank()) { + String credentials = Base64.getEncoder() + .encodeToString(("api:" + secret).getBytes(StandardCharsets.UTF_8)); + builder.header("Authorization", "Basic " + credentials); + } } - if (response.body().isBlank()) return new JsonObject(); - return JsonParser.parseString(response.body()).getAsJsonObject(); + + return client.send(builder.build(), HttpResponse.BodyHandlers.ofString()); } catch (IOException | InterruptedException e) { throw new IllegalStateException("API nicht erreichbar", e); } @@ -89,12 +99,4 @@ public final class Api { private static String config(String key) { return Main.globalConfig.node("api", key).getString(""); } - - public static boolean removeSecret(String username, String secret) { - Optional entry = find("secrets", "player", username, "secret", secret); - if (entry.isEmpty()) return false; - - send("DELETE", "secrets", "/" + entry.get().get("id").getAsString(), null); - return true; - } -} \ No newline at end of file +} diff --git a/src/main/java/eu/mhsl/craftattack/loginServer/Dialog.java b/src/main/java/eu/mhsl/craftattack/loginServer/Dialog.java index 8c2885a..c18fe60 100644 --- a/src/main/java/eu/mhsl/craftattack/loginServer/Dialog.java +++ b/src/main/java/eu/mhsl/craftattack/loginServer/Dialog.java @@ -83,11 +83,6 @@ public final class Dialog { String title; switch (state.currentPage()) { - case secret -> { - title = "Secret"; - body.add(plain("Bitte gib das Secret ein, das du erhalten hast.")); - inputs.add(text("secret", "Secret", state.secret, 50)); - } case data -> { title = "Profildaten"; body.add(plain("Bitte fülle deine Profildaten aus.")); @@ -158,7 +153,6 @@ public final class Dialog { private static void saveCurrentPage(DialogState state, CompoundBinaryTag payload) { switch (state.currentPage()) { - case secret -> state.secret = payload.getString("secret", "").trim(); case data -> { state.firstName = payload.getString("name", "").trim(); state.secondName = payload.getString("secondName", "").trim(); @@ -175,15 +169,6 @@ public final class Dialog { private static Component validateCurrentPage(Player player, DialogState state) { switch (state.currentPage()) { - case secret -> { - try { - if (!Api.isSecretValid(player.getUsername(), state.secret)) - return error("Das Secret ist ungültig."); - } catch (IllegalStateException e) { - e.printStackTrace(); - return error("Die Überprüfung ist gerade nicht möglich. Bitte versuche es später erneut."); - } - } case data -> { if (state.firstName.isBlank() || state.secondName.isBlank() || state.birthday.isBlank()) return error("Bitte fülle alle Pflichtfelder aus."); diff --git a/src/main/java/eu/mhsl/craftattack/loginServer/DialogState.java b/src/main/java/eu/mhsl/craftattack/loginServer/DialogState.java index 96c49ec..90a1a75 100644 --- a/src/main/java/eu/mhsl/craftattack/loginServer/DialogState.java +++ b/src/main/java/eu/mhsl/craftattack/loginServer/DialogState.java @@ -3,12 +3,11 @@ package eu.mhsl.craftattack.loginServer; import java.util.List; public final class DialogState { - public enum Page { secret, data, consent } + public enum Page { data, consent } - private final List pages; + private static final List pages = List.of(Page.data, Page.consent); private int pageIndex = 0; - String secret = ""; String firstName = ""; String secondName = ""; String birthday = ""; @@ -17,18 +16,10 @@ public final class DialogState { boolean logsAccepted = false; boolean rulesAccepted = false; - private DialogState(List pages) { - this.pages = pages; - } + private DialogState() {} public static DialogState create() { - boolean isAfterStart = Main.globalConfig - .node("server", "is-after-start") - .getBoolean(false); - - return new DialogState(isAfterStart - ? List.of(Page.secret, Page.data, Page.consent) - : List.of(Page.data, Page.consent)); + return new DialogState(); } public Page currentPage() { @@ -58,4 +49,4 @@ public final class DialogState { public void previousPage() { pageIndex = Math.max(0, pageIndex - 1); } -} \ No newline at end of file +} diff --git a/src/main/java/eu/mhsl/craftattack/loginServer/PlayerHandler.java b/src/main/java/eu/mhsl/craftattack/loginServer/PlayerHandler.java index a822693..e9de0ba 100644 --- a/src/main/java/eu/mhsl/craftattack/loginServer/PlayerHandler.java +++ b/src/main/java/eu/mhsl/craftattack/loginServer/PlayerHandler.java @@ -1,6 +1,7 @@ package eu.mhsl.craftattack.loginServer; import net.kyori.adventure.nbt.CompoundBinaryTag; +import net.kyori.adventure.text.Component; import net.minestom.server.MinecraftServer; import net.minestom.server.coordinate.Pos; import net.minestom.server.entity.Player; @@ -9,6 +10,9 @@ import net.minestom.server.event.player.PlayerCustomClickEvent; import net.minestom.server.instance.InstanceManager; import java.time.Duration; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.Locale; import java.util.Map; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; @@ -53,27 +57,51 @@ public final class PlayerHandler { private static void complete(Player player, DialogState state) { states.remove(player.getUuid()); - if (Api.isRegistered(player.getUuid())) { - player.kick("Du bist bereits auf Craftattack registriert, wir freuen uns auf dich!"); + String birthdayIso; + try { + birthdayIso = LocalDate + .parse(state.birthday, DateTimeFormatter.ofPattern("dd.MM.uuuu", Locale.GERMANY)) + .format(DateTimeFormatter.ISO_LOCAL_DATE); + } catch (RuntimeException e) { + player.kick(Component.text("Geburtsdatum ungültig.")); + return; + } + + try { + Api.signup( + state.firstName, + state.secondName, + birthdayIso, + state.phoneNumber, + player.getUsername(), + player.getUuid(), + "java" + ); + } catch (Api.SignupError e) { + e.printStackTrace(); + player.kick(Component.text(mapSignupError(e))); + return; + } catch (RuntimeException e) { + e.printStackTrace(); + player.kick(Component.text("Anmeldung gerade nicht möglich. Bitte später erneut versuchen.")); return; } player.sendMessage("Danke für deine Anmeldung."); player.sendMessage("Du bist für das Projekt Craftattack 9 registriert!"); - Api.setProfile(player.getUuid(), player.getUsername(), state.firstName, state.secondName, state.birthday, state.phoneNumber); - Api.removeSecret(player.getUsername(), state.secret); - MinecraftServer.getSchedulerManager() .buildTask(() -> player.kick("Anmeldung erfolgreich, wir freuen uns auf dich!")) .delay(Duration.ofMillis(1000)) .schedule(); - - System.out.println("Vorname: " + state.firstName); - System.out.println("Nachname: " + state.secondName); - System.out.println("Geburtstag: " + state.birthday); - System.out.println("Telefonnummer: " + state.phoneNumber); - System.out.println("Spielername: " + player.getUsername()); - System.out.println("Spieler UUID: " + player.getUuid()); } -} \ No newline at end of file + + private static String mapSignupError(Api.SignupError e) { + return switch (e.code) { + case "CONFLICT" -> "Du bist bereits registriert."; + case "UNAUTHORIZED" -> "Server nicht autorisiert. Bitte Admin kontaktieren."; + case "BAD_REQUEST" -> "Deine Angaben sind nicht gültig."; + default -> "Anmeldung fehlgeschlagen. Bitte später erneut versuchen."; + }; + } +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 3d2d258..279c26e 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -3,7 +3,6 @@ server: view-distance: 12 compression-threshold: 0 open-to-lan: false - is-after-start: false bungeecord: enabled: false @@ -15,5 +14,4 @@ velocity: api: url: "" - email: "" - password: "" \ No newline at end of file + secret: ""