From 2b18ca2debf15194f9332bfc74bf8699eca621d0 Mon Sep 17 00:00:00 2001 From: simoleo89 Date: Sun, 14 Jun 2026 20:20:00 +0200 Subject: [PATCH] fix(housekeeping): allow core rank peer actions Keep the housekeeping rank ceiling for normal staff, but treat the highest configured rank as the core rank so rank 7 can act on other rank 7 users without opening peer actions for lower staff ranks. Tests: mvn '-Dtest=HousekeepingTargetRankGuardContractTest,HousekeepingMutationGuardTest,HousekeepingSetUserRankEventTest,HousekeepingTargetRankGuardContractTest' test --- .../housekeeping/HousekeepingTargetRankGuard.java | 15 ++++++++++++++- .../HousekeepingTargetRankGuardContractTest.java | 10 +++++++--- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/Emulator/src/main/java/com/eu/habbo/messages/incoming/housekeeping/HousekeepingTargetRankGuard.java b/Emulator/src/main/java/com/eu/habbo/messages/incoming/housekeeping/HousekeepingTargetRankGuard.java index ee0e4965..e5623a7d 100644 --- a/Emulator/src/main/java/com/eu/habbo/messages/incoming/housekeeping/HousekeepingTargetRankGuard.java +++ b/Emulator/src/main/java/com/eu/habbo/messages/incoming/housekeeping/HousekeepingTargetRankGuard.java @@ -1,6 +1,7 @@ package com.eu.habbo.messages.incoming.housekeeping; import com.eu.habbo.Emulator; +import com.eu.habbo.habbohotel.permissions.Rank; import com.eu.habbo.habbohotel.users.Habbo; import com.eu.habbo.habbohotel.users.HabboInfo; @@ -18,6 +19,18 @@ final class HousekeepingTargetRankGuard { return true; } - return targetInfo.getRank().getId() < operator.getHabboInfo().getRank().getId(); + int operatorRankId = operator.getHabboInfo().getRank().getId(); + int targetRankId = targetInfo.getRank().getId(); + + return targetRankId < operatorRankId || isCoreRank(operatorRankId) && targetRankId <= operatorRankId; + } + + private static boolean isCoreRank(int rankId) { + int highestRankId = 0; + for (Rank rank : Emulator.getGameEnvironment().getPermissionsManager().getAllRanks()) { + highestRankId = Math.max(highestRankId, rank.getId()); + } + + return highestRankId > 0 && rankId >= highestRankId; } } diff --git a/Emulator/src/test/java/com/eu/habbo/messages/incoming/housekeeping/HousekeepingTargetRankGuardContractTest.java b/Emulator/src/test/java/com/eu/habbo/messages/incoming/housekeeping/HousekeepingTargetRankGuardContractTest.java index ed127abd..eaa3fc5f 100644 --- a/Emulator/src/test/java/com/eu/habbo/messages/incoming/housekeeping/HousekeepingTargetRankGuardContractTest.java +++ b/Emulator/src/test/java/com/eu/habbo/messages/incoming/housekeeping/HousekeepingTargetRankGuardContractTest.java @@ -24,11 +24,15 @@ class HousekeepingTargetRankGuardContractTest { ); @Test - void privilegedUserActionsRejectPeerAndHigherRankTargets() throws Exception { + void privilegedUserActionsRejectPeerRanksUnlessOperatorIsCoreRank() throws Exception { String guard = Files.readString(Path.of("src/main/java/com/eu/habbo/messages/incoming/housekeeping/HousekeepingTargetRankGuard.java")); - assertTrue(guard.contains("targetInfo.getRank().getId() < operator.getHabboInfo().getRank().getId()"), - "Housekeeping user actions must only target lower-ranked users"); + assertTrue(guard.contains("targetRankId < operatorRankId"), + "non-core housekeeping operators must only target lower-ranked users"); + assertTrue(guard.contains("isCoreRank(operatorRankId) && targetRankId <= operatorRankId"), + "the highest/core rank should be allowed to target peer ranks"); + assertTrue(guard.contains("private static boolean isCoreRank(int rankId)"), + "core-rank detection should be centralized in the target-rank guard"); } @Test