Fix issues with the permissions for using different player names

This adds separate permissions for accessing, creating and destroying of shops.
It also adds a config entry to allow using of a shop even if someone have access to it due to their permissions.
This commit is contained in:
Phoenix616 2018-11-19 21:10:48 +01:00
parent b17a471c21
commit b853afbd52
13 changed files with 136 additions and 62 deletions

View File

@ -74,6 +74,9 @@ public class Properties {
@ConfigurationComment("Do you want to allow using shops to people in creative mode?")
public static boolean IGNORE_CREATIVE_MODE = true;
@ConfigurationComment("Do you want to allow using shops to people who have access to it due to their permissions? (owners are always ignored)")
public static boolean IGNORE_ACCESS_PERMS = true;
@ConfigurationComment("If true, people will buy with left-click and sell with right-click.")
public static boolean REVERSE_BUTTONS = false;

View File

@ -1,11 +1,11 @@
package com.Acrobot.ChestShop.Listeners.Block.Break;
import com.Acrobot.ChestShop.Configuration.Properties;
import com.Acrobot.ChestShop.Listeners.Player.PlayerInteract;
import com.Acrobot.ChestShop.Plugins.ChestShop;
import com.Acrobot.ChestShop.Permission;
import com.Acrobot.ChestShop.Signs.ChestShopSign;
import com.Acrobot.ChestShop.Utils.uBlock;
import org.bukkit.block.Block;
import org.bukkit.block.Sign;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
@ -38,10 +38,14 @@ public class ChestBreak implements Listener {
}
private static boolean canBeBroken(Block block, Player breaker) {
if (!uBlock.couldBeShopContainer(block) || !Properties.USE_BUILT_IN_PROTECTION || !ChestShopSign.isShopChest(block)) {
if (!uBlock.couldBeShopContainer(block) || !Properties.USE_BUILT_IN_PROTECTION) {
return true;
}
return breaker != null && (PlayerInteract.canOpenOtherShops(breaker) || ChestShop.canAccess(breaker, block));
Sign shopSign = uBlock.findAnyNearbyShopSign(block);
if (breaker != null) {
return ChestShopSign.hasPermission(breaker, Permission.OTHER_NAME_DESTROY, shopSign);
}
return shopSign == null;
}
}

View File

@ -6,6 +6,7 @@ import com.Acrobot.ChestShop.Configuration.Properties;
import com.Acrobot.ChestShop.Events.ShopDestroyedEvent;
import com.Acrobot.ChestShop.Permission;
import com.Acrobot.ChestShop.Signs.ChestShopSign;
import com.Acrobot.ChestShop.UUIDs.NameManager;
import com.Acrobot.ChestShop.Utils.uBlock;
import org.bukkit.Material;
import org.bukkit.block.Block;
@ -30,10 +31,8 @@ import java.util.List;
import static com.Acrobot.Breeze.Utils.BlockUtil.getAttachedBlock;
import static com.Acrobot.Breeze.Utils.BlockUtil.isSign;
import static com.Acrobot.ChestShop.Permission.ADMIN;
import static com.Acrobot.ChestShop.Permission.MOD;
import static com.Acrobot.ChestShop.Permission.OTHER_NAME_DESTROY;
import static com.Acrobot.ChestShop.Signs.ChestShopSign.NAME_LINE;
import static com.Acrobot.ChestShop.UUIDs.NameManager.canUseName;
/**
* @author Acrobot
@ -151,11 +150,7 @@ public class SignBreak implements Listener {
}
private static boolean canDestroyShop(Player player, String name) {
return player != null && (hasShopBreakingPermission(player) || canUseName(player, name));
}
private static boolean hasShopBreakingPermission(Player player) {
return Permission.has(player, ADMIN) || Permission.has(player, MOD);
return player != null && NameManager.canUseName(player, OTHER_NAME_DESTROY, name);
}
private static void sendShopDestroyedEvent(Sign sign, Player player) {

View File

@ -35,6 +35,9 @@ import static com.Acrobot.Breeze.Utils.BlockUtil.isSign;
import static com.Acrobot.ChestShop.Events.TransactionEvent.TransactionType;
import static com.Acrobot.ChestShop.Events.TransactionEvent.TransactionType.BUY;
import static com.Acrobot.ChestShop.Events.TransactionEvent.TransactionType.SELL;
import static com.Acrobot.ChestShop.Permission.OTHER_NAME_ACCESS;
import static com.Acrobot.ChestShop.Permission.OTHER_NAME_CREATE;
import static com.Acrobot.ChestShop.Permission.OTHER_NAME_DESTROY;
import static com.Acrobot.ChestShop.Signs.ChestShopSign.*;
import static org.bukkit.event.block.Action.LEFT_CLICK_BLOCK;
import static org.bukkit.event.block.Action.RIGHT_CLICK_BLOCK;
@ -58,7 +61,7 @@ public class PlayerInteract implements Listener {
return;
}
if (!canOpenOtherShops(player) && !ChestShop.canAccess(player, block)) {
if (!ChestShop.canAccess(player, block)) {
player.sendMessage(Messages.prefix(Messages.ACCESS_DENIED));
event.setCancelled(true);
}
@ -66,7 +69,7 @@ public class PlayerInteract implements Listener {
return;
}
if (!isSign(block) || player.getItemInHand().getType() == Material.SIGN) // Blocking accidental sign edition
if (!isSign(block) || player.getInventory().getItemInMainHand().getType() == Material.SIGN) // Blocking accidental sign edition
return;
Sign sign = (Sign) block.getState();
@ -74,10 +77,8 @@ public class PlayerInteract implements Listener {
return;
}
boolean canAccess = ChestShopSign.canAccess(player, sign);
if (Properties.ALLOW_AUTO_ITEM_FILL && ChatColor.stripColor(sign.getLine(ITEM_LINE)).equals(AUTOFILL_CODE)) {
if (canAccess) {
if (ChestShopSign.hasPermission(player, OTHER_NAME_CREATE, sign)) {
ItemStack item = player.getInventory().getItemInMainHand();
if (!MaterialUtil.isEmpty(item)) {
String itemCode = MaterialUtil.getSignName(item);
@ -101,19 +102,22 @@ public class PlayerInteract implements Listener {
return;
}
if (canAccess && !ChestShopSign.isAdminShop(sign)) {
if (!Properties.ALLOW_SIGN_CHEST_OPEN
|| player.isSneaking() || player.isInsideVehicle()
|| (Properties.IGNORE_CREATIVE_MODE && player.getGameMode() == GameMode.CREATIVE)) {
if (ChestShopSign.hasPermission(player, OTHER_NAME_ACCESS, sign) && !ChestShopSign.isAdminShop(sign)) {
if (Properties.ALLOW_SIGN_CHEST_OPEN) {
if (player.isSneaking() || player.isInsideVehicle()
|| (Properties.IGNORE_CREATIVE_MODE && player.getGameMode() == GameMode.CREATIVE)
|| (Properties.ALLOW_LEFT_CLICK_DESTROYING && action == LEFT_CLICK_BLOCK
&& ChestShopSign.hasPermission(player, OTHER_NAME_DESTROY, sign))) {
return;
}
event.setCancelled(true);
showChestGUI(player, block, sign);
return;
} else if (Properties.IGNORE_ACCESS_PERMS || ChestShopSign.isOwner(player, sign)) {
// don't allow owners or people with access to buy/sell at this shop
return;
}
if (!Properties.ALLOW_LEFT_CLICK_DESTROYING || action != LEFT_CLICK_BLOCK) {
event.setCancelled(true);
showChestGUI(player, block);
}
return;
}
if (action == RIGHT_CLICK_BLOCK) {
@ -212,19 +216,23 @@ public class PlayerInteract implements Listener {
}
}
/**
* @deprecated Use {@link ChestShopSign#hasPermission(Player, Permission, Sign)} with {@link Permission#OTHER_NAME_ACCESS}
*/
@Deprecated
public static boolean canOpenOtherShops(Player player) {
return Permission.has(player, Permission.ADMIN) || Permission.has(player, Permission.MOD);
return Permission.has(player, Permission.OTHER_NAME_ACCESS + ".*");
}
private static void showChestGUI(Player player, Block signBlock) {
Container container = uBlock.findConnectedContainer(signBlock);
private static void showChestGUI(Player player, Block signBlock, Sign sign) {
Container container = uBlock.findConnectedContainer(sign);
if (container == null) {
player.sendMessage(Messages.prefix(Messages.NO_CHEST_DETECTED));
return;
}
if (!canOpenOtherShops(player) && !Security.canAccess(player, signBlock)) {
if (!Security.canAccess(player, signBlock)) {
return;
}

View File

@ -43,7 +43,7 @@ public class PlayerInventory implements Listener {
chest = ((DoubleChest) event.getInventory().getHolder()).getLocation().getBlock();
}
if (!PlayerInteract.canOpenOtherShops(player) && !ChestShop.canAccess(player, chest)) {
if (!ChestShop.canAccess(player, chest)) {
player.sendMessage(Messages.prefix(Messages.ACCESS_DENIED));
event.setCancelled(true);
}

View File

@ -9,6 +9,7 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import static com.Acrobot.ChestShop.Permission.OTHER_NAME_CREATE;
import static com.Acrobot.ChestShop.Signs.ChestShopSign.NAME_LINE;
import static com.Acrobot.ChestShop.Events.PreShopCreationEvent.CreationOutcome.UNKNOWN_PLAYER;
@ -22,7 +23,7 @@ public class NameChecker implements Listener {
String name = event.getSignLine(NAME_LINE);
Player player = event.getPlayer();
if (name.isEmpty() || !NameManager.canUseName(player, name)) {
if (name.isEmpty() || !NameManager.canUseName(player, OTHER_NAME_CREATE, name)) {
Account account = NameManager.getAccount(player.getName());
if (account != null) {
event.setSignLine(NAME_LINE, account.getShortName());

View File

@ -4,6 +4,8 @@ import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.Optional;
/**
* @author Acrobot
*/
@ -24,8 +26,12 @@ public enum Permission {
SELL("ChestShop.shop.sell"),
ADMIN("ChestShop.admin"),
ADMIN_SHOP("ChestShop.adminshop"),
MOD("ChestShop.mod"),
OTHER_NAME("ChestShop.name."),
OTHER_NAME("ChestShop.name"),
OTHER_NAME_CREATE("ChestShop.othername.create"),
OTHER_NAME_DESTROY("ChestShop.othername.destroy"),
OTHER_NAME_ACCESS("ChestShop.othername.access"),
GROUP("ChestShop.group."),
NOFEE("ChestShop.nofee"),
@ -48,15 +54,21 @@ public enum Permission {
}
public static boolean otherName(Player player, String name) {
if (has(player, Permission.ADMIN)) {
return true;
}
return hasPermissionSet(player, OTHER_NAME + name) || hasPermissionSet(player, OTHER_NAME + name.toLowerCase());
return otherName(player, OTHER_NAME, name);
}
private static boolean hasPermissionSet(CommandSender sender, String permission) {
return sender.isPermissionSet(permission) && sender.hasPermission(permission);
public static boolean otherName(Player player, Permission base, String name) {
boolean hasBase = base != OTHER_NAME && otherName(player, OTHER_NAME, name);
if (hasBase || has(player, base + ".*")) {
return !hasPermissionSetFalse(player, base+ "." + name) && !hasPermissionSetFalse(player, base + "." + name.toLowerCase());
}
return has(player, base + "." + name) || has(player, base + "." + name.toLowerCase());
}
private static boolean hasPermissionSetFalse(CommandSender sender, String permission) {
return (sender.isPermissionSet(permission) && !sender.hasPermission(permission))
|| (sender.isPermissionSet(permission.toLowerCase()) && !sender.hasPermission(permission.toLowerCase()));
}
public static org.bukkit.permissions.Permission getPermission(Permission permission) {

View File

@ -33,7 +33,7 @@ public class ChestShop implements Listener {
}
public static boolean canAccess(Player player, Block block) {
if (Permission.has(player, Permission.ADMIN) || !canBeProtected(block)) {
if (!canBeProtected(block)) {
return true;
}
@ -65,6 +65,6 @@ public class ChestShop implements Listener {
}
private static boolean isShopMember(Player player, Sign sign) {
return NameManager.canUseName(player, sign.getLine(ChestShopSign.NAME_LINE));
return ChestShopSign.hasPermission(player, Permission.OTHER_NAME_ACCESS, sign);
}
}

View File

@ -4,6 +4,8 @@ import com.Acrobot.Breeze.Utils.BlockUtil;
import com.Acrobot.Breeze.Utils.StringUtil;
import com.Acrobot.ChestShop.Configuration.Properties;
import com.Acrobot.ChestShop.Containers.AdminInventory;
import com.Acrobot.ChestShop.Database.Account;
import com.Acrobot.ChestShop.Permission;
import com.Acrobot.ChestShop.UUIDs.NameManager;
import com.Acrobot.ChestShop.Utils.uBlock;
import org.bukkit.block.Block;
@ -102,13 +104,30 @@ public class ChestShopSign {
}
public static boolean canAccess(Player player, Sign sign) {
return hasPermission(player, Permission.OTHER_NAME_ACCESS, sign);
}
public static boolean hasPermission(Player player, Permission base, Sign sign) {
if (player == null) return false;
if (sign == null) return true;
String name = sign.getLine(NAME_LINE);
if (name == null || name.isEmpty()) return true;
return NameManager.canUseName(player, name);
return NameManager.canUseName(player, base, name);
}
public static boolean isOwner(Player player, Sign sign) {
if (player == null || sign == null) return false;
String name = sign.getLine(NAME_LINE);
if (name == null || name.isEmpty()) return false;
Account account = NameManager.getAccountFromShortName(name);
if (account == null) {
return player.getName().equalsIgnoreCase(name);
}
return account.getUuid().equals(player.getUniqueId());
}
public static boolean isValidPreparedSign(String[] lines) {

View File

@ -58,8 +58,9 @@ public class RestrictedSign implements Listener {
Sign sign = (Sign) connectedSign.getState();
if (!ChestShopSign.canAccess(player, sign)) {
if (!ChestShopSign.hasPermission(player, Permission.OTHER_NAME_DESTROY, sign)) {
dropSignAndCancelEvent(event);
return;
}
player.sendMessage(Messages.prefix(Messages.RESTRICTED_SIGN_CREATED));
@ -129,16 +130,11 @@ public class RestrictedSign implements Listener {
public static boolean canAccess(Sign sign, Player player) {
Block blockUp = sign.getBlock().getRelative(BlockFace.UP);
return !BlockUtil.isSign(blockUp) || hasPermission(player, ((Sign) blockUp.getState()).getLines());
}
public static boolean canDestroy(Player player, Sign sign) {
if (Permission.has(player, ADMIN)) {
return true;
}
Sign shopSign = getAssociatedSign(sign);
return ChestShopSign.canAccess(player, shopSign);
return ChestShopSign.hasPermission(player, Permission.OTHER_NAME_DESTROY, shopSign);
}
public static Sign getAssociatedSign(Sign restricted) {
@ -152,7 +148,7 @@ public class RestrictedSign implements Listener {
}
for (String line : lines) {
if (p.hasPermission(Permission.GROUP.toString() + line)) {
if (Permission.has(p, Permission.GROUP + line)) {
return true;
}
}

View File

@ -22,6 +22,8 @@ import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import static com.Acrobot.ChestShop.Permission.OTHER_NAME;
/**
* Lets you save/cache username and UUID relations
*
@ -295,18 +297,26 @@ public class NameManager {
return shortenedName;
}
/**
* @deprecated Use {@link #canUseName(Player, Permission, String)} to provide specific information about how the player wants to use the name
*/
@Deprecated
public static boolean canUseName(Player player, String name) {
return canUseName(player, OTHER_NAME, name);
}
public static boolean canUseName(Player player, Permission base, String name) {
if (ChestShopSign.isAdminShop(name)) {
return Permission.has(player, Permission.ADMIN);
return Permission.has(player, Permission.ADMIN_SHOP);
}
if (Permission.otherName(player, name)) {
if (Permission.otherName(player, base, name)) {
return true;
}
Account account = getAccountFromShortName(name, false);
return account != null && (account.getUuid().equals(player.getUniqueId())
|| (!account.getName().equalsIgnoreCase(name) && Permission.otherName(player, account.getName())));
|| (!account.getName().equalsIgnoreCase(name) && Permission.otherName(player, base, account.getName())));
}
public static boolean isAdminShop(UUID uuid) {

View File

@ -3,6 +3,7 @@ package com.Acrobot.ChestShop.Utils;
import com.Acrobot.Breeze.Utils.BlockUtil;
import com.Acrobot.ChestShop.Configuration.Properties;
import com.Acrobot.ChestShop.Signs.ChestShopSign;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
@ -67,7 +68,7 @@ public class uBlock {
}
/**
* @deprecated Use {@link #findConnectedContainer(Block, BlockFace)}
* @deprecated Use {@link #findConnectedContainer(Location, BlockFace)}
*/
@Deprecated
private static org.bukkit.block.Chest findConnectedChest(Block block, BlockFace signFace) {
@ -94,7 +95,7 @@ public class uBlock {
if (((org.bukkit.material.Sign) sign.getData()).isWallSign()) {
signFace = ((Attachable) sign.getData()).getAttachedFace();
}
return findConnectedContainer(sign.getBlock(), signFace);
return findConnectedContainer(sign.getLocation(), signFace);
}
public static Container findConnectedContainer(Block block) {
@ -105,12 +106,12 @@ public class uBlock {
signFace = ((Attachable) sign.getData()).getAttachedFace();
}
}
return findConnectedContainer(block, signFace);
return findConnectedContainer(block.getLocation(), signFace);
}
private static Container findConnectedContainer(Block block, BlockFace signFace) {
private static Container findConnectedContainer(Location location, BlockFace signFace) {
if (signFace != null) {
Block faceBlock = block.getRelative(signFace);
Block faceBlock = location.clone().add(signFace.getModX(), signFace.getModY(), signFace.getModZ()).getBlock();
if (uBlock.couldBeShopContainer(faceBlock)) {
return (Container) faceBlock.getState();
}
@ -118,7 +119,7 @@ public class uBlock {
for (BlockFace bf : SHOP_FACES) {
if (bf != signFace) {
Block faceBlock = block.getRelative(bf);
Block faceBlock = location.clone().add(bf.getModX(), bf.getModY(), bf.getModZ()).getBlock();
if (uBlock.couldBeShopContainer(faceBlock)) {
return (Container) faceBlock.getState();
}

View File

@ -71,10 +71,35 @@ permissions:
ChestShop.admin:
description: Allows user to modify/destroy other stores and create an Admin Shops
default: op
children:
ChestShop.adminshop: true
ChestShop.name.*: true
ChestShop.adminshop:
description: Allows user to create and destroy Admin Shops
ChestShop.mod:
description: Allows user only to view other store chests, he can't destroy them or create an Admin Shop
children:
ChestShop.name.access.*: true
ChestShop.name.*:
description: Gives you the power to do create and access shops for all names.
children:
ChestShop.name.create.*: true
ChestShop.name.destroy.*: true
ChestShop.name.access.*: true
ChestShop.name.(some name):
description: Gives you the power to do create and access shops for (some name), for example your town.
ChestShop.name.create.*:
description: Gives you the power to do create shops for all names.
ChestShop.name.create.(some name):
description: Gives you the power to do create shops for (some name), for example your town.
ChestShop.name.destroy.*:
description: Gives you the power to do destroy shops with all names.
ChestShop.name.destroy.(some name):
description: Gives you the power to do destroy shops with (some name), for example your town.
ChestShop.name.access.*:
description: Gives you the power to do access shops for all names.
ChestShop.name.access.(some name):
description: Gives you the power to do access shops for (some name), for example your town.
ChestShop.shop.create.food:
description: Allows to create a shop that sells food
children: