update
This commit is contained in:
1 parent
3f672d1819
commit
15d1c70b8c
5 files changed
+103
-99
No files matched your search
@@ -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<String> 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();
|
||||
public static final class SignupError extends RuntimeException {
|
||||
public final String code;
|
||||
public SignupError(String code, String message) {
|
||||
super(message);
|
||||
this.code = code;
|
||||
}
|
||||
}
|
||||
|
||||
private static Optional<JsonObject> 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 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);
|
||||
|
||||
HttpResponse<String> 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);
|
||||
}
|
||||
|
||||
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"));
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
private static JsonObject call(String method, String path, JsonObject body, String token) {
|
||||
private static HttpResponse<String> 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<String> 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<JsonObject> entry = find("secrets", "player", username, "secret", secret);
|
||||
if (entry.isEmpty()) return false;
|
||||
|
||||
send("DELETE", "secrets", "/" + entry.get().get("id").getAsString(), null);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -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.");
|
||||
|
||||
@@ -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<Page> pages;
|
||||
private static final List<Page> 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<Page> 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() {
|
||||
|
||||
@@ -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());
|
||||
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.";
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -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: ""
|
||||
secret: ""
|
||||
Reference in new issue
Block a user