Redstone on islands will operate if mods or ops are present

even if the offline redstone flag is active and no team members are
online. This enables staff to bypass the "Offline Redstone" feature,
which means if staff need to moderate players islands then redstone is
an issue.

Fixes https://github.com/BentoBoxWorld/BentoBox/issues/1102
This commit is contained in:
tastybento 2020-01-07 17:20:04 -08:00
parent 90ad75baa9
commit 1c500a0c05
2 changed files with 66 additions and 2 deletions

View File

@ -24,15 +24,23 @@ public class OfflineRedstoneListener extends FlagListener {
return;
}
// Check if island exists and members are online - excludes spawn
// Check if island exists and members are online, or mods or ops are on the island - ignores spawn
getIslands().getProtectedIslandAt(e.getBlock().getLocation())
.filter(i -> !i.isSpawn())
.ifPresent(i -> {
// Check team members
for (UUID uuid : i.getMemberSet(RanksManager.COOP_RANK)) {
if (Bukkit.getPlayer(uuid) != null) {
return;
}
}
// Check mods or Ops on island
if (Bukkit.getOnlinePlayers().parallelStream()
.filter(p -> p.isOp() || p.hasPermission(getIWM().getPermissionPrefix(i.getWorld()) + "mod.bypassprotect"))
.anyMatch(p -> i.onIsland(p.getLocation()))) {
return;
}
// No one there...
e.setNewCurrent(0);
});
}

View File

@ -7,8 +7,10 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import org.bukkit.Bukkit;
@ -23,6 +25,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.stubbing.Answer;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
@ -43,6 +46,8 @@ import world.bentobox.bentobox.util.Util;
@PrepareForTest({BentoBox.class, Util.class, Bukkit.class })
public class OfflineRedstoneListenerTest {
private static final String[] NAMES = {"adam", "ben", "cara", "dave", "ed", "frank", "freddy", "george", "harry", "ian", "joe"};
@Mock
private World world;
@Mock
@ -100,6 +105,19 @@ public class OfflineRedstoneListenerTest {
when(iwm.getAddon(any())).thenReturn(Optional.empty());
PowerMockito.mockStatic(Bukkit.class);
// Online players
Set<Player> onlinePlayers = new HashSet<>();
for (int j = 0; j < NAMES.length; j++) {
Player p1 = mock(Player.class);
UUID u = UUID.randomUUID();
when(p1.getUniqueId()).thenReturn(u);
when(p1.getName()).thenReturn(NAMES[j]);
// All ops
when(p1.isOp()).thenReturn(true);
onlinePlayers.add(p1);
}
when(Bukkit.getOnlinePlayers()).then((Answer<Set<Player>>) invocation -> onlinePlayers);
}
@After
@ -150,7 +168,7 @@ public class OfflineRedstoneListenerTest {
OfflineRedstoneListener orl = new OfflineRedstoneListener();
// Offline redstone not allowed
Flags.OFFLINE_REDSTONE.setSetting(world, false);
// Members are online
// Members are offline
when(Bukkit.getPlayer(any(UUID.class))).thenReturn(null);
orl.onBlockRedstone(e);
@ -158,6 +176,44 @@ public class OfflineRedstoneListenerTest {
assertEquals(0, e.getNewCurrent());
}
/**
* Test method for {@link OfflineRedstoneListener#onBlockRedstone(BlockRedstoneEvent)}.
*/
@Test
public void testOnBlockRedstoneMembersOfflineOpsOnlineNotOnIsland() {
// Make an event to give some current to block
BlockRedstoneEvent e = new BlockRedstoneEvent(block, 0, 10);
OfflineRedstoneListener orl = new OfflineRedstoneListener();
// Offline redstone not allowed
Flags.OFFLINE_REDSTONE.setSetting(world, false);
// Members are offline
when(Bukkit.getPlayer(any(UUID.class))).thenReturn(null);
orl.onBlockRedstone(e);
// Current will be 0
assertEquals(0, e.getNewCurrent());
}
/**
* Test method for {@link OfflineRedstoneListener#onBlockRedstone(BlockRedstoneEvent)}.
*/
@Test
public void testOnBlockRedstoneMembersOfflineOpsOnlineOnIsland() {
// Make an event to give some current to block
BlockRedstoneEvent e = new BlockRedstoneEvent(block, 0, 10);
OfflineRedstoneListener orl = new OfflineRedstoneListener();
// Offline redstone not allowed
Flags.OFFLINE_REDSTONE.setSetting(world, false);
// Members are offline
when(Bukkit.getPlayer(any(UUID.class))).thenReturn(null);
// On island
when(island.onIsland(any())).thenReturn(true);
orl.onBlockRedstone(e);
// Current remains 10
assertEquals(10, e.getNewCurrent());
}
/**
* Test method for {@link OfflineRedstoneListener#onBlockRedstone(BlockRedstoneEvent)}.
*/