Add better perms handling and a way to disable options for constructing disguises

This commit is contained in:
Andrew 2013-11-12 17:46:39 +13:00
parent f02d212c9b
commit c1ada67da6

View File

@ -2,7 +2,9 @@ package me.libraryaddict.disguise;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import me.libraryaddict.disguise.disguisetypes.AnimalColor;
import me.libraryaddict.disguise.disguisetypes.Disguise;
@ -18,17 +20,41 @@ import org.bukkit.entity.Horse.Style;
import org.bukkit.entity.Ocelot.Type;
import org.bukkit.entity.Villager.Profession;
import org.bukkit.inventory.ItemStack;
import org.bukkit.permissions.PermissionAttachmentInfo;
import org.bukkit.potion.PotionEffectType;
public abstract class BaseDisguiseCommand implements CommandExecutor {
protected ArrayList<String> getAllowedDisguises(CommandSender sender, String permissionNode) {
ArrayList<String> names = new ArrayList<String>();
for (DisguiseType type : DisguiseType.values()) {
String name = type.name().toLowerCase();
if (sender.hasPermission("libsdisguises." + permissionNode + ".*")
|| sender.hasPermission("libsdisguises." + permissionNode + "." + name))
names.add(name);
ArrayList<String> forbiddenDisguises = new ArrayList<String>();
for (PermissionAttachmentInfo permission : sender.getEffectivePermissions()) {
String perm = permission.getPermission().toLowerCase();
if (perm.startsWith(permissionNode)) {
perm = perm.substring(permissionNode.length());
for (DisguiseType type : DisguiseType.values()) {
String name = type.name().toLowerCase();
if (perm.split("//.")[0].equals("*") && permission.getValue()) {
names.add(name);
} else if (perm.split("//.")[0].equals(name)) {
if (permission.getValue()) {
names.add(name);
} else {
forbiddenDisguises.add(name);
}
}
}
}
}
for (DisguiseType type : DisguiseType.values()) {
if (!names.contains(type.name().toLowerCase())) {
if (sender.hasPermission(permissionNode + "*")
|| sender.hasPermission(permissionNode + type.name().toLowerCase())) {
names.add(type.name().toLowerCase());
}
}
}
names.removeAll(forbiddenDisguises);
Collections.sort(names, String.CASE_INSENSITIVE_ORDER);
return names;
}
@ -51,13 +77,41 @@ public abstract class BaseDisguiseCommand implements CommandExecutor {
}
}
/**
* Returns null if they have all perms. Else they can only use the options in the returned
*/
protected HashSet<HashSet<String>> getPermissions(CommandSender sender, String disguiseType) {
HashSet<HashSet<String>> perms = new HashSet<HashSet<String>>();
String permNode = "libsdisguises." + getClass().getSimpleName().replace("Command", "").toLowerCase() + ".";
for (PermissionAttachmentInfo permission : sender.getEffectivePermissions()) {
if (permission.getValue()) {
String s = permission.getPermission().toLowerCase();
if (s.startsWith(permNode + disguiseType) || s.startsWith(permNode + "*")) {
if (s.startsWith(permNode + disguiseType))
s = s.substring((permNode + disguiseType).length());
else if (s.startsWith(permNode + "*")) {
s = s.substring((permNode + "*").length());
if (s.length() == 0)
continue;
}
if (s.length() == 0)
return new HashSet<HashSet<String>>();
HashSet<String> p = new HashSet<String>();
p.addAll(Arrays.asList(s.split("\\.")));
perms.add(p);
}
}
}
return perms;
}
/**
* Returns the disguise if it all parsed correctly. Returns a exception with a complete message if it didn't. The
* commandsender is purely used for checking permissions. Would defeat the purpose otherwise. To reach this point, the
* disguise has been feed a proper disguisetype.
*/
protected Disguise parseDisguise(CommandSender sender, String[] args) throws Exception {
String permissionNode = getClass().getSimpleName().replace("Command", "").toLowerCase();
String permissionNode = "libsdisguises." + getClass().getSimpleName().replace("Command", "").toLowerCase() + ".";
ArrayList<String> allowedDisguises = getAllowedDisguises(sender, permissionNode);
if (allowedDisguises.isEmpty()) {
throw new Exception(ChatColor.RED + "You are forbidden to use this command.");
@ -80,11 +134,14 @@ public abstract class BaseDisguiseCommand implements CommandExecutor {
if (!allowedDisguises.contains(disguiseType.name().toLowerCase())) {
throw new Exception(ChatColor.RED + "You are forbidden to use this disguise!");
}
HashSet<String> usedOptions = new HashSet<String>();
Disguise disguise = null;
// How many args to skip due to the disugise being constructed
int toSkip = 1;
// Time to start constructing the disguise.
// We will need to check between all 3 kinds of disguises
HashSet<HashSet<String>> optionPermissions = this.getPermissions(sender, disguiseType.name().toLowerCase());
if (disguiseType.isPlayer()) {// If he is doing a player disguise
if (args.length == 1) {
// He needs to give the player name
@ -99,11 +156,15 @@ public abstract class BaseDisguiseCommand implements CommandExecutor {
boolean adult = true;
if (args.length > 1) {
if (args[1].equalsIgnoreCase("true") || args[1].equalsIgnoreCase("false")) {
usedOptions.add("setbaby");
doCheck(optionPermissions, usedOptions);
adult = "false".equalsIgnoreCase(args[1]);
sender.sendMessage(ChatColor.RED
+ "I notice you are using true/false for constructing a mob disguise! This will soon be removed in favor of the simple 'baby'");
toSkip++;
} else if (args[1].equalsIgnoreCase("baby")) {
usedOptions.add("setbaby");
doCheck(optionPermissions, usedOptions);
adult = false;
toSkip++;
}
@ -138,7 +199,6 @@ public abstract class BaseDisguiseCommand implements CommandExecutor {
newArgs[i - toSkip] = args[i];
}
args = newArgs;
// Don't throw a error about uneven methods names and values so we can throw the error about what is unknown later.
for (int i = 0; i < args.length; i += 2) {
String methodName = args[i];
if (i + 1 >= args.length) {
@ -266,12 +326,25 @@ public abstract class BaseDisguiseCommand implements CommandExecutor {
if (methodToUse == null) {
throw new Exception(ChatColor.RED + "Cannot find the option " + methodName);
}
usedOptions.add(methodName.toLowerCase());
doCheck(optionPermissions, usedOptions);
methodToUse.invoke(disguise.getWatcher(), value);
}
// Alright. We've constructed our disguise.
return disguise;
}
private void doCheck(HashSet<HashSet<String>> optionPermissions, HashSet<String> usedOptions) throws Exception {
if (!optionPermissions.isEmpty()) {
for (HashSet<String> perms : optionPermissions) {
if (!perms.containsAll(usedOptions)) {
throw new Exception(ChatColor.RED + "You do not have the permission to use the option "
+ usedOptions.iterator().next());
}
}
}
}
private Exception parseToException(String expectedValue, String receivedInstead, String methodName) {
return new Exception(ChatColor.RED + "Expected " + ChatColor.GREEN + expectedValue + ChatColor.RED + ", received "
+ ChatColor.GREEN + receivedInstead + ChatColor.RED + " instead for " + ChatColor.GREEN + methodName);