Skip to content

Commit 5bae6ee

Browse files
strobilXephi
authored andcommitted
fix(premium): send authoritative premium list to proxy when disabled or empty
The proxy.started handler queried stored premium usernames without checking settings.enablePremium and skipped the send entirely when the list was empty, so the proxy kept a stale premium_names.cache and went on verifying enrolled players after the feature was disabled on the backend. Gate the DB query on enablePremium and always send the list: an empty list is authoritative and makes the proxy replace and persist an empty cache. Both proxies already handle a zero-name chunked list. Fixes #3127
1 parent 8b41f72 commit 5bae6ee

2 files changed

Lines changed: 76 additions & 16 deletions

File tree

‎authme-core/src/main/java/fr/xephi/authme/service/bungeecord/BungeeReceiver.java‎

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import fr.xephi.authme.service.ProxyLoginRequestValidator;
1515
import fr.xephi.authme.settings.Settings;
1616
import fr.xephi.authme.settings.properties.HooksSettings;
17+
import fr.xephi.authme.settings.properties.PremiumSettings;
1718
import fr.xephi.authme.util.UuidUtils;
1819
import org.bukkit.entity.Player;
1920
import org.bukkit.plugin.messaging.Messenger;
@@ -42,6 +43,7 @@ public class BungeeReceiver implements PluginMessageListener, SettingsDependent
4243
private static final long MAX_AGE_MILLIS = 30_000L;
4344

4445
private boolean isEnabled;
46+
private boolean premiumEnabled;
4547
private String proxySharedSecret;
4648
private boolean channelRegistered;
4749

@@ -63,6 +65,7 @@ public class BungeeReceiver implements PluginMessageListener, SettingsDependent
6365
public void reload(Settings settings) {
6466
this.proxySharedSecret = settings.getProperty(HooksSettings.PROXY_SHARED_SECRET);
6567
this.isEnabled = settings.getProperty(HooksSettings.BUNGEECORD);
68+
this.premiumEnabled = settings.getProperty(PremiumSettings.ENABLE_PREMIUM);
6669
final Messenger messenger = plugin.getServer().getMessenger();
6770
if (messenger == null) {
6871
return;
@@ -112,22 +115,23 @@ public void onPluginMessageReceived(String channel, Player player, byte[] data)
112115
logger.info("Proxy plugin '" + argument + "' has started and registered the authme:main channel");
113116
final String proxyName = argument;
114117
bukkitService.runTaskAsynchronously(() -> {
115-
List<String> premiumNames = dataSource.getPremiumUsernames();
116-
if (!premiumNames.isEmpty()) {
117-
bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(() -> {
118-
// Re-fetch a carrier at send-time: the original player may have gone offline
119-
// during the async DB query.
120-
Player freshCarrier = bukkitService.getOnlinePlayers().stream()
121-
.findFirst().orElse(null);
122-
if (freshCarrier != null) {
123-
bungeeSender.sendPremiumList(freshCarrier, premiumNames);
124-
logger.info("Sent premium list (" + premiumNames.size() + " player(s)) to proxy '" + proxyName + "'");
125-
} else {
126-
logger.warning("Cannot send premium list to proxy '" + proxyName
127-
+ "': no online player available as carrier.");
128-
}
129-
});
130-
}
118+
// Always send the list, even when it is empty: an empty list is authoritative and
119+
// lets the proxy replace a stale premium cache. With premium disabled, stored
120+
// premium names must not reach the proxy, or it keeps verifying those players.
121+
List<String> premiumNames = premiumEnabled ? dataSource.getPremiumUsernames() : List.of();
122+
bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(() -> {
123+
// Re-fetch a carrier at send-time: the original player may have gone offline
124+
// during the async DB query.
125+
Player freshCarrier = bukkitService.getOnlinePlayers().stream()
126+
.findFirst().orElse(null);
127+
if (freshCarrier != null) {
128+
bungeeSender.sendPremiumList(freshCarrier, premiumNames);
129+
logger.info("Sent premium list (" + premiumNames.size() + " player(s)) to proxy '" + proxyName + "'");
130+
} else {
131+
logger.warning("Cannot send premium list to proxy '" + proxyName
132+
+ "': no online player available as carrier.");
133+
}
134+
});
131135
});
132136
return;
133137
}

‎authme-core/src/test/java/fr/xephi/authme/service/bungeecord/BungeeReceiverTest.java‎

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import fr.xephi.authme.service.ProxyLoginRequestValidator;
1313
import fr.xephi.authme.settings.Settings;
1414
import fr.xephi.authme.settings.properties.HooksSettings;
15+
import fr.xephi.authme.settings.properties.PremiumSettings;
1516
import org.bukkit.Server;
1617
import org.bukkit.entity.Player;
1718
import org.bukkit.plugin.messaging.Messenger;
@@ -24,10 +25,12 @@
2425
import org.mockito.junit.jupiter.MockitoSettings;
2526
import org.mockito.quality.Strictness;
2627

28+
import java.util.List;
2729
import java.util.UUID;
2830

2931
import static fr.xephi.authme.service.BukkitServiceTestHelper.setBukkitServiceToRunTaskAsynchronously;
3032
import static fr.xephi.authme.service.BukkitServiceTestHelper.setBukkitServiceToScheduleSyncEntityTaskFromOptionallyAsyncTask;
33+
import static fr.xephi.authme.service.BukkitServiceTestHelper.setBukkitServiceToScheduleSyncTaskFromOptionallyAsyncTask;
3134
import static org.hamcrest.MatcherAssert.assertThat;
3235
import static org.hamcrest.Matchers.equalTo;
3336
import static org.hamcrest.Matchers.nullValue;
@@ -81,6 +84,7 @@ static void initLogger() {
8184
void setUp() {
8285
given(plugin.getServer()).willReturn(server);
8386
given(server.getMessenger()).willReturn(messenger);
87+
given(settings.getProperty(PremiumSettings.ENABLE_PREMIUM)).willReturn(true);
8488
}
8589

8690
@Test
@@ -288,6 +292,58 @@ void shouldRejectConfigPhasePerformLoginWithInvalidHmac() {
288292
verify(proxySessionManager, never()).processProxySessionMessage(any(), any());
289293
}
290294

295+
@Test
296+
void shouldSendEmptyPremiumListOnProxyStartedWhenPremiumIsDisabled() {
297+
// given
298+
given(settings.getProperty(HooksSettings.BUNGEECORD)).willReturn(true);
299+
given(settings.getProperty(PremiumSettings.ENABLE_PREMIUM)).willReturn(false);
300+
setBukkitServiceToRunTaskAsynchronously(bukkitService);
301+
setBukkitServiceToScheduleSyncTaskFromOptionallyAsyncTask(bukkitService);
302+
303+
Player carrier = mock(Player.class);
304+
given(bukkitService.getOnlinePlayers()).willReturn(List.of(carrier));
305+
306+
BungeeReceiver receiver =
307+
new BungeeReceiver(plugin, bukkitService, proxySessionManager, management, bungeeSender, dataSource,
308+
proxyLoginRequestValidator, settings);
309+
310+
// when
311+
receiver.onPluginMessageReceived("authme:main", carrier, buildProxyStartedPayload("velocity"));
312+
313+
// then
314+
verify(dataSource, never()).getPremiumUsernames();
315+
verify(bungeeSender).sendPremiumList(carrier, List.of());
316+
}
317+
318+
@Test
319+
void shouldSendEmptyPremiumListOnProxyStartedWhenNoPremiumUsersAreStored() {
320+
// given
321+
given(settings.getProperty(HooksSettings.BUNGEECORD)).willReturn(true);
322+
given(dataSource.getPremiumUsernames()).willReturn(List.of());
323+
setBukkitServiceToRunTaskAsynchronously(bukkitService);
324+
setBukkitServiceToScheduleSyncTaskFromOptionallyAsyncTask(bukkitService);
325+
326+
Player carrier = mock(Player.class);
327+
given(bukkitService.getOnlinePlayers()).willReturn(List.of(carrier));
328+
329+
BungeeReceiver receiver =
330+
new BungeeReceiver(plugin, bukkitService, proxySessionManager, management, bungeeSender, dataSource,
331+
proxyLoginRequestValidator, settings);
332+
333+
// when
334+
receiver.onPluginMessageReceived("authme:main", carrier, buildProxyStartedPayload("velocity"));
335+
336+
// then
337+
verify(bungeeSender).sendPremiumList(carrier, List.of());
338+
}
339+
340+
private static byte[] buildProxyStartedPayload(String proxyName) {
341+
ByteArrayDataOutput out = ByteStreams.newDataOutput();
342+
out.writeUTF(MessageType.PROXY_STARTED.getId());
343+
out.writeUTF(proxyName);
344+
return out.toByteArray();
345+
}
346+
291347
private static byte[] buildPerformLoginPayload(String playerName, long timestamp, String hmac) {
292348
return buildPerformLoginPayload(playerName, timestamp, "", hmac);
293349
}

0 commit comments

Comments
 (0)