diff --git a/Emulator/src/main/java/com/eu/habbo/messages/rcon/SetRank.java b/Emulator/src/main/java/com/eu/habbo/messages/rcon/SetRank.java index e05bee9e..496db38d 100644 --- a/Emulator/src/main/java/com/eu/habbo/messages/rcon/SetRank.java +++ b/Emulator/src/main/java/com/eu/habbo/messages/rcon/SetRank.java @@ -5,6 +5,10 @@ import com.eu.habbo.habbohotel.users.Habbo; import com.google.gson.Gson; import jakarta.validation.constraints.Positive; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; + public class SetRank extends RCONMessage { public SetRank() { @@ -13,6 +17,25 @@ public class SetRank extends RCONMessage { @Override public void handle(Gson gson, JSONSetRank object) { + int maxRank = SetRankRequestGuard.parseMaxRank( + Emulator.getConfig().getValue("rcon.setrank.max_rank", String.valueOf(SetRankRequestGuard.DEFAULT_MAX_RANK))); + String validationError = SetRankRequestGuard.validate( + object.user_id, + object.rank, + maxRank, + rankId -> Emulator.getGameEnvironment().getPermissionsManager().rankExists(rankId)); + if (validationError != null) { + this.status = RCONMessage.STATUS_ERROR; + this.message = validationError; + return; + } + + if (!userExists(object.user_id)) { + this.status = RCONMessage.HABBO_NOT_FOUND; + this.message = "user not found"; + return; + } + try { Emulator.getGameEnvironment().getHabboManager().setRank(object.user_id, object.rank); } catch (Exception e) { @@ -30,6 +53,23 @@ public class SetRank extends RCONMessage { } } + private static boolean userExists(int userId) { + Habbo habbo = Emulator.getGameEnvironment().getHabboManager().getHabbo(userId); + if (habbo != null) { + return true; + } + + try (Connection connection = Emulator.getDatabase().getDataSource().getConnection(); + PreparedStatement statement = connection.prepareStatement("SELECT id FROM users WHERE id = ? LIMIT 1")) { + statement.setInt(1, userId); + try (ResultSet set = statement.executeQuery()) { + return set.next(); + } + } catch (Exception e) { + return false; + } + } + static class JSONSetRank { @Positive(message = "invalid user") diff --git a/Emulator/src/main/java/com/eu/habbo/messages/rcon/SetRankRequestGuard.java b/Emulator/src/main/java/com/eu/habbo/messages/rcon/SetRankRequestGuard.java new file mode 100644 index 00000000..aa55344a --- /dev/null +++ b/Emulator/src/main/java/com/eu/habbo/messages/rcon/SetRankRequestGuard.java @@ -0,0 +1,39 @@ +package com.eu.habbo.messages.rcon; + +import java.util.function.IntPredicate; + +public class SetRankRequestGuard { + public static final int DEFAULT_MAX_RANK = 12; + + private SetRankRequestGuard() { + } + + public static String validate(int userId, int rankId, int maxRank, IntPredicate rankExists) { + if (userId <= 0) { + return "invalid user"; + } + + if (rankId <= 0) { + return "invalid rank"; + } + + if (maxRank > 0 && rankId > maxRank) { + return "rank exceeds rcon ceiling"; + } + + if (!rankExists.test(rankId)) { + return "invalid rank"; + } + + return null; + } + + public static int parseMaxRank(String rawValue) { + try { + int value = Integer.parseInt(rawValue); + return value > 0 ? value : DEFAULT_MAX_RANK; + } catch (Exception e) { + return DEFAULT_MAX_RANK; + } + } +} diff --git a/Emulator/src/test/java/com/eu/habbo/messages/rcon/SetRankRequestGuardTest.java b/Emulator/src/test/java/com/eu/habbo/messages/rcon/SetRankRequestGuardTest.java new file mode 100644 index 00000000..a4ae0431 --- /dev/null +++ b/Emulator/src/test/java/com/eu/habbo/messages/rcon/SetRankRequestGuardTest.java @@ -0,0 +1,32 @@ +package com.eu.habbo.messages.rcon; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +class SetRankRequestGuardTest { + @Test + void acceptsKnownRanksWithinTheRconCeiling() { + assertNull(SetRankRequestGuard.validate(1, 5, 12, rankId -> rankId == 5)); + } + + @Test + void rejectsInvalidUsersRanksAndUnknownRanks() { + assertEquals("invalid user", SetRankRequestGuard.validate(0, 5, 12, rankId -> true)); + assertEquals("invalid rank", SetRankRequestGuard.validate(1, 0, 12, rankId -> true)); + assertEquals("invalid rank", SetRankRequestGuard.validate(1, 5, 12, rankId -> false)); + } + + @Test + void rejectsRanksAboveConfiguredCeiling() { + assertEquals("rank exceeds rcon ceiling", SetRankRequestGuard.validate(1, 13, 12, rankId -> true)); + } + + @Test + void parsesInvalidMaxRankAsDefaultCeiling() { + assertEquals(SetRankRequestGuard.DEFAULT_MAX_RANK, SetRankRequestGuard.parseMaxRank(null)); + assertEquals(SetRankRequestGuard.DEFAULT_MAX_RANK, SetRankRequestGuard.parseMaxRank("0")); + assertEquals(7, SetRankRequestGuard.parseMaxRank("7")); + } +}