diff --git a/src/main/java/world/bentobox/bentobox/database/objects/Island.java b/src/main/java/world/bentobox/bentobox/database/objects/Island.java index 1c2fa534d..344c41260 100644 --- a/src/main/java/world/bentobox/bentobox/database/objects/Island.java +++ b/src/main/java/world/bentobox/bentobox/database/objects/Island.java @@ -607,6 +607,9 @@ public class Island implements DataObject, MetaDataAble { * @return rank integer */ public int getRank(User user) { + if (user.isOp()) { + return RanksManager.ADMIN_RANK; + } return members.getOrDefault(user.getUniqueId(), RanksManager.VISITOR_RANK); } diff --git a/src/main/java/world/bentobox/bentobox/listeners/flags/clicklisteners/CommandRankClickListener.java b/src/main/java/world/bentobox/bentobox/listeners/flags/clicklisteners/CommandRankClickListener.java index fcdb4c1a6..766d3ce68 100644 --- a/src/main/java/world/bentobox/bentobox/listeners/flags/clicklisteners/CommandRankClickListener.java +++ b/src/main/java/world/bentobox/bentobox/listeners/flags/clicklisteners/CommandRankClickListener.java @@ -4,7 +4,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Objects; -import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.Sound; import org.bukkit.World; @@ -16,12 +15,14 @@ import world.bentobox.bentobox.api.localization.TextVariables; import world.bentobox.bentobox.api.panels.Panel; import world.bentobox.bentobox.api.panels.PanelItem; import world.bentobox.bentobox.api.panels.PanelItem.ClickHandler; +import world.bentobox.bentobox.api.panels.TabbedPanel; import world.bentobox.bentobox.api.panels.builders.PanelBuilder; import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder; import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.database.objects.Island; import world.bentobox.bentobox.lists.Flags; import world.bentobox.bentobox.managers.RanksManager; +import world.bentobox.bentobox.panels.settings.SettingsTab; import world.bentobox.bentobox.util.Util; /** @@ -31,12 +32,19 @@ import world.bentobox.bentobox.util.Util; public class CommandRankClickListener implements ClickHandler { private final BentoBox plugin = BentoBox.getInstance(); + private Island island; /* (non-Javadoc) * @see world.bentobox.bentobox.api.panels.PanelItem.ClickHandler#onClick(world.bentobox.bentobox.api.panels.Panel, world.bentobox.bentobox.api.user.User, org.bukkit.event.inventory.ClickType, int) */ @Override public boolean onClick(Panel panel, User user, ClickType clickType, int slot) { + // This click listener is used with TabbedPanel and SettingsTabs only + TabbedPanel tp = (TabbedPanel)panel; + SettingsTab st = (SettingsTab)tp.getActiveTab(); + // Get the island for this tab + island = st.getIsland(); + // Get the world if (!user.inWorld()) { user.sendMessage("general.errors.wrong-world"); @@ -55,17 +63,16 @@ public class CommandRankClickListener implements ClickHandler { return true; } - // Get the user's island - Island island = plugin.getIslands().getIsland(panel.getWorld().orElse(user.getWorld()), user.getUniqueId()); - if (island == null || island.getOwner() == null || !island.isAllowed(user, Flags.CHANGE_SETTINGS)) { - user.sendMessage("general.errors.insufficient-rank", - TextVariables.RANK, - user.getTranslation(plugin.getRanksManager().getRank(Objects.requireNonNull(island).getRank(user)))); - + // Check if user has rank enough on the island + //Island island = plugin.getIslands().getIsland(panel.getWorld().orElse(user.getWorld()), user.getUniqueId()); + if (!island.isAllowed(user, Flags.CHANGE_SETTINGS)) { + String rank = user.getTranslation(plugin.getRanksManager().getRank(Objects.requireNonNull(island).getRank(user))); + user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, rank); user.getPlayer().playSound(user.getLocation(), Sound.BLOCK_METAL_HIT, 1F, 1F); return true; } + String panelName = user.getTranslation("protection.flags.COMMAND_RANKS.name"); if (panel.getName().equals(panelName)) { // This is a click on the panel @@ -100,7 +107,6 @@ public class CommandRankClickListener implements ClickHandler { * @return panel item for this command */ public PanelItem getPanelItem(String c, User user, World world) { - Island island = plugin.getIslands().getIsland(world, user); PanelItemBuilder pib = new PanelItemBuilder(); pib.name(c); pib.clickHandler(new CommandCycleClick(this, c)); @@ -126,7 +132,7 @@ public class CommandRankClickListener implements ClickHandler { .filter(c -> c.getWorld() != null && c.getWorld().equals(world)) .forEach(c -> result.addAll(getCmdRecursively("/", c))); if (result.size() > 49) { - Bukkit.getLogger().severe("Number of rank setting commands is too big for GUI"); + plugin.logError("Number of rank setting commands is too big for GUI"); result.subList(49, result.size()).clear(); } return result; diff --git a/src/test/java/world/bentobox/bentobox/listeners/flags/clicklisteners/CommandRankClickListenerTest.java b/src/test/java/world/bentobox/bentobox/listeners/flags/clicklisteners/CommandRankClickListenerTest.java new file mode 100644 index 000000000..732846657 --- /dev/null +++ b/src/test/java/world/bentobox/bentobox/listeners/flags/clicklisteners/CommandRankClickListenerTest.java @@ -0,0 +1,247 @@ +package world.bentobox.bentobox.listeners.flags.clicklisteners; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.World; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.Inventory; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; +import org.junit.After; +import org.junit.Before; +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; +import org.powermock.reflect.Whitebox; + +import world.bentobox.bentobox.BentoBox; +import world.bentobox.bentobox.api.addons.GameModeAddon; +import world.bentobox.bentobox.api.commands.CompositeCommand; +import world.bentobox.bentobox.api.localization.TextVariables; +import world.bentobox.bentobox.api.panels.PanelItem; +import world.bentobox.bentobox.api.panels.TabbedPanel; +import world.bentobox.bentobox.api.user.User; +import world.bentobox.bentobox.database.objects.Island; +import world.bentobox.bentobox.lists.Flags; +import world.bentobox.bentobox.managers.CommandsManager; +import world.bentobox.bentobox.managers.IslandWorldManager; +import world.bentobox.bentobox.managers.IslandsManager; +import world.bentobox.bentobox.managers.RanksManager; +import world.bentobox.bentobox.panels.settings.SettingsTab; +import world.bentobox.bentobox.util.Util; + +/** + * @author tastybento + * + */ +@RunWith(PowerMockRunner.class) +@PrepareForTest({Bukkit.class, BentoBox.class, Util.class}) +public class CommandRankClickListenerTest { + @Mock + private User user; + @Mock + private World world; + @Mock + private TabbedPanel panel; + @Mock + private BentoBox plugin; + @Mock + private IslandWorldManager iwm; + @Mock + private @NonNull Inventory inv; + @Mock + private GameModeAddon gma; + + private CommandRankClickListener crcl; + @Mock + private Player player; + @Mock + private IslandsManager im; + @Mock + private @Nullable Island island; + + private UUID uuid = UUID.randomUUID(); + private RanksManager rm; + @Mock + private CommandsManager cm; + @Mock + private SettingsTab tab; + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() throws Exception { + + // Bukkit + PowerMockito.mockStatic(Bukkit.class, Mockito.RETURNS_MOCKS); + // Set up plugin + Whitebox.setInternalState(BentoBox.class, "instance", plugin); + // Island + when(island.getOwner()).thenReturn(uuid); + when(island.isAllowed(user, Flags.CHANGE_SETTINGS)).thenReturn(true); + when(island.getRankCommand(anyString())).thenReturn(RanksManager.MEMBER_RANK); + // IM + when(plugin.getIslands()).thenReturn(im); + when(im.getIsland(world, uuid)).thenReturn(island); + when(im.getIsland(world, user)).thenReturn(island); + // IWM + when(plugin.getIWM()).thenReturn(iwm); + when(iwm.getAddon(any())).thenReturn(Optional.of(gma)); + when(iwm.getPermissionPrefix(world)).thenReturn("oneblock."); + // Panel + when(panel.getInventory()).thenReturn(inv); + when(panel.getWorld()).thenReturn(Optional.of(world)); + when(panel.getName()).thenReturn("protection.flags.COMMAND_RANKS.name"); + when(panel.getActiveTab()).thenReturn(tab); + // Tab + when(tab.getIsland()).thenReturn(island); + // User + when(user.getUniqueId()).thenReturn(uuid); + when(user.hasPermission(anyString())).thenReturn(true); + when(user.getPlayer()).thenReturn(player); + when(user.inWorld()).thenReturn(true); + when(user.getWorld()).thenReturn(world); + when(user.getTranslation(anyString())).thenAnswer((Answer) invocation -> invocation.getArgument(0, String.class)); + when(user.getTranslation(anyString(),anyString(),anyString())).thenAnswer((Answer) invocation -> invocation.getArgument(0, String.class)); + + // Util + PowerMockito.mockStatic(Util.class, Mockito.CALLS_REAL_METHODS); + when(Util.getWorld(any())).thenReturn(world); + // RanksManager + rm = new RanksManager(); + when(plugin.getRanksManager()).thenReturn(rm); + // Commands Manager + when(plugin.getCommandsManager()).thenReturn(cm); + Map map = new HashMap<>(); + CompositeCommand cc = mock(CompositeCommand.class); + when(cc.getWorld()).thenReturn(world); + when(cc.isConfigurableRankCommand()).thenReturn(true); + when(cc.getName()).thenReturn("test"); + when(cc.getSubCommands()).thenReturn(Collections.emptyMap()); + map.put("test", cc); + when(cm.getCommands()).thenReturn(map); + crcl = new CommandRankClickListener(); + } + + /** + * @throws java.lang.Exception + */ + @After + public void tearDown() throws Exception { + Mockito.framework().clearInlineMocks(); + } + + /** + * Test method for {@link world.bentobox.bentobox.listeners.flags.clicklisteners.CommandRankClickListener#onClick(world.bentobox.bentobox.api.panels.Panel, world.bentobox.bentobox.api.user.User, org.bukkit.event.inventory.ClickType, int)}. + */ + @Test + public void testOnClickWrongWorld() { + when(user.inWorld()).thenReturn(false); + assertTrue(crcl.onClick(panel, user, ClickType.LEFT, 0)); + verify(user).sendMessage("general.errors.wrong-world"); + } + + /** + * Test method for {@link world.bentobox.bentobox.listeners.flags.clicklisteners.CommandRankClickListener#onClick(world.bentobox.bentobox.api.panels.Panel, world.bentobox.bentobox.api.user.User, org.bukkit.event.inventory.ClickType, int)}. + */ + @Test + public void testOnClickNoPermission() { + when(user.hasPermission(anyString())).thenReturn(false); + assertTrue(crcl.onClick(panel, user, ClickType.LEFT, 0)); + verify(user).sendMessage("general.errors.no-permission", TextVariables.PERMISSION, "oneblock.settings.COMMAND_RANKS"); + verify(player).playSound(user.getLocation(), Sound.BLOCK_METAL_HIT, 1F, 1F); + } + + /** + * Test method for {@link world.bentobox.bentobox.listeners.flags.clicklisteners.CommandRankClickListener#onClick(world.bentobox.bentobox.api.panels.Panel, world.bentobox.bentobox.api.user.User, org.bukkit.event.inventory.ClickType, int)}. + */ + @Test + public void testOnClickNoFlag() { + when(island.isAllowed(user, Flags.CHANGE_SETTINGS)).thenReturn(false); + assertTrue(crcl.onClick(panel, user, ClickType.LEFT, 0)); + verify(user).sendMessage("general.errors.insufficient-rank", TextVariables.RANK, "ranks.visitor"); + verify(player).playSound(user.getLocation(), Sound.BLOCK_METAL_HIT, 1F, 1F); + } + + /** + * Test method for {@link world.bentobox.bentobox.listeners.flags.clicklisteners.CommandRankClickListener#onClick(world.bentobox.bentobox.api.panels.Panel, world.bentobox.bentobox.api.user.User, org.bukkit.event.inventory.ClickType, int)}. + */ + @Test + public void testOnClickDifferentPanelName() { + when(panel.getName()).thenReturn("different"); + assertTrue(crcl.onClick(panel, user, ClickType.LEFT, 0)); + verify(inv, never()).setItem(eq(0), any()); + verify(user).closeInventory(); + } + + /** + * Test method for {@link world.bentobox.bentobox.listeners.flags.clicklisteners.CommandRankClickListener#onClick(world.bentobox.bentobox.api.panels.Panel, world.bentobox.bentobox.api.user.User, org.bukkit.event.inventory.ClickType, int)}. + */ + @Test + public void testOnClick() { + assertTrue(crcl.onClick(panel, user, ClickType.LEFT, 0)); + verify(inv).setItem(eq(0), any()); + } + + /** + * Test method for {@link world.bentobox.bentobox.listeners.flags.clicklisteners.CommandRankClickListener#onClick(world.bentobox.bentobox.api.panels.Panel, world.bentobox.bentobox.api.user.User, org.bukkit.event.inventory.ClickType, int)}. + */ + @Test + public void testOnClickTooManyCommands() { + Map map = new HashMap<>(); + for (int i = 0; i < 55; i++) { + CompositeCommand cc = mock(CompositeCommand.class); + when(cc.getWorld()).thenReturn(world); + when(cc.isConfigurableRankCommand()).thenReturn(true); + when(cc.getName()).thenReturn("test" + i); + when(cc.getSubCommands()).thenReturn(Collections.emptyMap()); + map.put("test" + i, cc); + } + when(cm.getCommands()).thenReturn(map); + + assertTrue(crcl.onClick(panel, user, ClickType.LEFT, 0)); + verify(plugin).logError("Number of rank setting commands is too big for GUI"); + } + + + + /** + * Test method for {@link world.bentobox.bentobox.listeners.flags.clicklisteners.CommandRankClickListener#getPanelItem(java.lang.String, world.bentobox.bentobox.api.user.User, org.bukkit.World)}. + */ + @Test + public void testGetPanelItem() { + assertTrue(crcl.onClick(panel, user, ClickType.LEFT, 0)); + PanelItem pi = crcl.getPanelItem("test", user, world); + assertEquals(Material.MAP, pi.getItem().getType()); + assertEquals("protection.panel.flag-item.description-layout", pi.getDescription().get(0)); + assertEquals("protection.panel.flag-item.minimal-rankranks.member", pi.getDescription().get(1)); + assertEquals("protection.panel.flag-item.allowed-rankranks.sub-owner", pi.getDescription().get(2)); + assertEquals("protection.panel.flag-item.allowed-rankranks.owner", pi.getDescription().get(3)); + assertTrue(pi.getClickHandler().isPresent()); + assertEquals("test", pi.getName()); + } + +}