fix(guilds): only accept pending memberships

Guard the guild acceptance update with level_id = REQUESTED so a stale or concurrent accept cannot promote a membership row that has already changed state.

Tests: mvn '-Dtest=GuildManagerMembershipContractTest,GuildMembershipManagementContractTest,GuildMembershipRequestContractTest' test
This commit is contained in:
simoleo89
2026-06-14 20:19:45 +02:00
parent 7a7e38311d
commit 8db6281cc8
2 changed files with 26 additions and 1 deletions
@@ -291,11 +291,12 @@ public class GuildManager {
}
}
} else if (!error) {
try (PreparedStatement statement = connection.prepareStatement("UPDATE guilds_members SET level_id = ?, member_since = ? WHERE user_id = ? AND guild_id = ?")) {
try (PreparedStatement statement = connection.prepareStatement("UPDATE guilds_members SET level_id = ?, member_since = ? WHERE user_id = ? AND guild_id = ? AND level_id = ?")) {
statement.setInt(1, GuildRank.MEMBER.type);
statement.setInt(2, Emulator.getIntUnixTimestamp());
statement.setInt(3, userId);
statement.setInt(4, guild.getId());
statement.setInt(5, GuildRank.REQUESTED.type);
statement.execute();
}
}
@@ -0,0 +1,24 @@
package com.eu.habbo.habbohotel.guilds;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.nio.file.Files;
import java.nio.file.Path;
import org.junit.jupiter.api.Test;
class GuildManagerMembershipContractTest {
private static String guildManagerSource() throws Exception {
return Files.readString(Path.of("src/main/java/com/eu/habbo/habbohotel/guilds/GuildManager.java"));
}
@Test
void acceptRequestOnlyPromotesPendingMembershipRows() throws Exception {
String source = guildManagerSource();
assertTrue(source.contains("UPDATE guilds_members SET level_id = ?, member_since = ? WHERE user_id = ? AND guild_id = ? AND level_id = ?"),
"accepting a guild request must only promote rows still in REQUESTED state");
assertTrue(source.contains("statement.setInt(5, GuildRank.REQUESTED.type);"),
"the accept-request update must bind the expected REQUESTED rank guard");
}
}