Skip to content

Commit

Permalink
Added rudimentary SignChangeEvent permission check
Browse files Browse the repository at this point in the history
- MOD: Cleaned up imports
- NEW: SignEditCommits now run validation by pretending to blank the
       sign to see if the player has permission to edit the sign.
- MOD: Reorganized the tests
- NEW: Added SignEditCommitTest for SignEditCommit testing
  • Loading branch information
Deltik committed Dec 8, 2017
1 parent 58e6e16 commit 8e955e1
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 62 deletions.
6 changes: 1 addition & 5 deletions src/org/deltik/mc/signedit/Main.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
package org.deltik.mc.signedit;

import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
import org.deltik.mc.signedit.commands.SignCommand;
import org.deltik.mc.signedit.listeners.Interact;

import java.io.PrintWriter;
import java.io.StringWriter;

public class Main extends JavaPlugin {
public static final String CHAT_PREFIX = "§7[§cSignEdit§7]§r ";
public static Main instance;
Expand All @@ -21,7 +17,7 @@ public void onEnable() {
config = new Configuration();
listener = new Interact();
signCommand = new SignCommand(config, listener);
for (String alias : new String[] {"sign", "signedit", "editsign", "se"}) {
for (String alias : new String[]{"sign", "signedit", "editsign", "se"}) {
this.getCommand(alias).setExecutor(signCommand);
}
getServer().getPluginManager().registerEvents(listener, this);
Expand Down
18 changes: 17 additions & 1 deletion src/org/deltik/mc/signedit/committers/SignEditCommit.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,25 @@

import org.bukkit.block.Sign;
import org.bukkit.entity.Player;
import org.bukkit.event.block.SignChangeEvent;

import static org.bukkit.Bukkit.getServer;
import static org.deltik.mc.signedit.Main.CHAT_PREFIX;

public interface SignEditCommit {
void commit(Player player, Sign sign);

default void cleanup() {}
default void cleanup() {
}

default void validatedCommit(Player player, Sign sign) {
// Simulates blanking the sign to check if editing this sign is allowed
SignChangeEvent event = new SignChangeEvent(sign.getBlock(), player, new String[]{"", "", "", ""});
getServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
player.sendMessage(CHAT_PREFIX + "§cSign edit forbidden by policy or other plugin");
return;
}
commit(player, sign);
}
}
2 changes: 1 addition & 1 deletion src/org/deltik/mc/signedit/listeners/Interact.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public void onInteract(PlayerInteractEvent event) {

if (isCommitPending(player)) {
SignEditCommit commit = popSignEditCommit(player);
commit.commit(player, sign);
commit.validatedCommit(player, sign);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/org/deltik/mc/signedit/subcommands/SignSubcommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ boolean autocommit(SignEditCommit commit) {
player.sendMessage(CHAT_PREFIX + "§cNow right-click a sign to edit it");
} else if (block.getState() instanceof Sign) {
Sign sign = (Sign) block.getState();
commit.commit(player, sign);
commit.validatedCommit(player, sign);
} else {
player.sendMessage(CHAT_PREFIX + "§cYou must be looking at a sign to edit it!");
return false;
Expand Down
55 changes: 1 addition & 54 deletions test/SignCommandTest.java
Original file line number Diff line number Diff line change
@@ -1,72 +1,19 @@
import org.bukkit.block.Block;
import org.bukkit.block.Sign;
import org.bukkit.command.Command;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.event.block.Action;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.deltik.mc.signedit.Configuration;
import org.deltik.mc.signedit.commands.SignCommand;
import org.deltik.mc.signedit.committers.SignEditCommit;
import org.deltik.mc.signedit.listeners.Interact;
import org.deltik.mc.signedit.subcommands.UiSignSubcommand;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

import java.io.File;

import static org.mockito.ArgumentMatchers.matches;
import static org.mockito.Mockito.*;
import static org.powermock.api.mockito.PowerMockito.doReturn;
import static org.powermock.api.mockito.PowerMockito.mock;
import static org.powermock.api.mockito.PowerMockito.spy;
import static org.powermock.api.mockito.PowerMockito.when;
import static org.powermock.api.mockito.PowerMockito.*;

@RunWith(PowerMockRunner.class)
@PrepareForTest({PlayerInteractEvent.class, SignCommand.class})
public class SignCommandTest {
private SignCommand signCommand;
private Player player;
private Command command;
private Sign sign;
private Block block;
private Configuration spyConfig;
private Interact listener;
private String cString = "signedit";
private UiSignSubcommand uiSignSubcommand;

@Before
public void setUp() throws Exception {
Configuration config = new Configuration(File.createTempFile("SignEdit-", "-config.yml"));
spyConfig = spy(config);
listener = new Interact();
doReturn(false).when(spyConfig).writeFullConfig(new YamlConfiguration());

uiSignSubcommand = mock(UiSignSubcommand.class);
whenNew(UiSignSubcommand.class).withAnyArguments().thenReturn(uiSignSubcommand);

signCommand = new SignCommand(spyConfig, listener);

player = mock(Player.class);
command = mock(Command.class);
sign = mock(Sign.class);
block = mock(Block.class);
when(player.hasPermission("SignEdit.use")).thenReturn(true);
when(block.getState()).thenReturn(sign);
}

@After
public void validate() {
validateMockitoUsage();
}

public class SignCommandTest extends SignEditTest {
@Test
public void signLineShouldUpdateWhenLookingAtSignAndAllowedToEditBySight() {
String argsString = "set 1 alpha bravo charlie";
Expand Down
40 changes: 40 additions & 0 deletions test/SignEditCommitTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import org.bukkit.event.block.SignChangeEvent;
import org.deltik.mc.signedit.committers.SignEditCommit;
import org.deltik.mc.signedit.committers.UiSignEditCommit;
import org.junit.Test;
import org.powermock.core.classloader.annotations.PrepareForTest;

import static org.mockito.ArgumentMatchers.matches;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.powermock.api.mockito.PowerMockito.*;

@PrepareForTest({SignEditCommit.class})
public class SignEditCommitTest extends SignEditTest {
@Test
public void validatedCommitForbiddenSignEdit() throws Exception {
SignEditCommit spySignEditCommit = spy(new UiSignEditCommit(null, null));
SignChangeEvent event = mock(SignChangeEvent.class);
whenNew(SignChangeEvent.class).withAnyArguments().thenReturn(event);
doReturn(true).when(event).isCancelled();
doNothing().when(spySignEditCommit).commit(player, sign);

spySignEditCommit.validatedCommit(player, sign);

verify(spySignEditCommit, never()).commit(player, sign);
verify(player).sendMessage(matches("(?i)^.*edit.*forbidden.*$"));
}

@Test
public void validatedCommitPermittedSignEdit() throws Exception {
SignEditCommit spySignEditCommit = spy(new UiSignEditCommit(null, null));
SignChangeEvent event = mock(SignChangeEvent.class);
whenNew(SignChangeEvent.class).withAnyArguments().thenReturn(event);
doReturn(false).when(event).isCancelled();
doNothing().when(spySignEditCommit).commit(player, sign);

spySignEditCommit.validatedCommit(player, sign);

verify(spySignEditCommit).commit(player, sign);
}
}
70 changes: 70 additions & 0 deletions test/SignEditTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import org.bukkit.Bukkit;
import org.bukkit.Server;
import org.bukkit.block.Block;
import org.bukkit.block.Sign;
import org.bukkit.command.Command;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.plugin.PluginManager;
import org.deltik.mc.signedit.Configuration;
import org.deltik.mc.signedit.commands.SignCommand;
import org.deltik.mc.signedit.listeners.Interact;
import org.deltik.mc.signedit.subcommands.UiSignSubcommand;
import org.junit.After;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

import java.io.File;

import static org.mockito.Mockito.validateMockitoUsage;
import static org.powermock.api.mockito.PowerMockito.*;

@RunWith(PowerMockRunner.class)
@PrepareForTest({Bukkit.class, PlayerInteractEvent.class, SignCommand.class})
public abstract class SignEditTest {
SignCommand signCommand;
Player player;
Command command;
Sign sign;
Block block;
Configuration spyConfig;
Interact listener;
String cString = "signedit";
UiSignSubcommand uiSignSubcommand;
Server server;
PluginManager pluginManager;

@Before
public void setUp() throws Exception {
Configuration config = new Configuration(File.createTempFile("SignEdit-", "-config.yml"));
spyConfig = spy(config);
listener = new Interact();
doReturn(false).when(spyConfig).writeFullConfig(new YamlConfiguration());

uiSignSubcommand = mock(UiSignSubcommand.class);
whenNew(UiSignSubcommand.class).withAnyArguments().thenReturn(uiSignSubcommand);

signCommand = new SignCommand(spyConfig, listener);

player = mock(Player.class);
command = mock(Command.class);
sign = mock(Sign.class);
block = mock(Block.class);
when(player.hasPermission("SignEdit.use")).thenReturn(true);
when(block.getState()).thenReturn(sign);

server = mock(Server.class);
pluginManager = mock(PluginManager.class);
mockStatic(Bukkit.class);
when(Bukkit.getServer()).thenReturn(server);
when(server.getPluginManager()).thenReturn(pluginManager);
}

@After
public void validate() {
validateMockitoUsage();
}
}

0 comments on commit 8e955e1

Please sign in to comment.