diff --git a/src/main/java/cpw/mods/fml/common/event/FMLServerStartingEvent.java b/src/main/java/cpw/mods/fml/common/event/FMLServerStartingEvent.java index 1f7d8e1..ecdd612 100644 --- a/src/main/java/cpw/mods/fml/common/event/FMLServerStartingEvent.java +++ b/src/main/java/cpw/mods/fml/common/event/FMLServerStartingEvent.java @@ -16,6 +16,11 @@ import net.minecraft.command.ICommand; import net.minecraft.server.MinecraftServer; import cpw.mods.fml.common.LoaderState.ModState; +import org.ultramine.commands.CommandRegistry; +import org.ultramine.commands.IExtendedCommand; +import org.ultramine.commands.syntax.ArgumentsPatternParser; +import org.ultramine.commands.syntax.IArgumentCompletionHandler; +import org.ultramine.commands.syntax.IArgumentValidationHandler; public class FMLServerStartingEvent extends FMLStateEvent { @@ -43,4 +48,41 @@ CommandHandler ch = (CommandHandler) getServer().getCommandManager(); ch.registerCommand(command); } + + /* ========================================= ULTRAMINE START ======================================*/ + + public void registerCommand(IExtendedCommand command) + { + getCommandRegistry().registerCommand(command); + } + + public void registerCommands(Class holder) + { + getCommandRegistry().registerCommands(holder); + } + + public void registerArgumentHandler(String argumentType, IArgumentCompletionHandler handler) + { + getArgumentsParser().registerHandler(argumentType, handler); + } + + public void registerArgumentHandler(String argumentType, IArgumentValidationHandler handler) + { + getArgumentsParser().registerHandler(argumentType, handler); + } + + public void registerArgumentHandlers(Class holder) + { + getArgumentsParser().registerHandlers(holder); + } + + private CommandRegistry getCommandRegistry() + { + return ((CommandHandler) getServer().getCommandManager()).getRegistry(); + } + + private ArgumentsPatternParser getArgumentsParser() + { + return getCommandRegistry().getArgumentsParser(); + } } \ No newline at end of file diff --git a/src/main/java/net/minecraft/command/CommandHandler.java b/src/main/java/net/minecraft/command/CommandHandler.java index b47cd0c..75bbf63 100644 --- a/src/main/java/net/minecraft/command/CommandHandler.java +++ b/src/main/java/net/minecraft/command/CommandHandler.java @@ -1,13 +1,7 @@ package net.minecraft.command; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Set; -import java.util.Map.Entry; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.util.ChatComponentTranslation; import net.minecraft.util.EnumChatFormatting; @@ -16,12 +10,12 @@ import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.CommandEvent; +import org.ultramine.commands.CommandRegistry; public class CommandHandler implements ICommandManager { private static final Logger logger = LogManager.getLogger(); - private final Map commandMap = new HashMap(); - private final Set commandSet = new HashSet(); + private final CommandRegistry registry = new CommandRegistry(); private static final String __OBFID = "CL_00001765"; public int executeCommand(ICommandSender par1ICommandSender, String par2Str) @@ -36,7 +30,7 @@ String[] astring = par2Str.split(" "); String s1 = astring[0]; astring = dropFirstString(astring); - ICommand icommand = (ICommand)this.commandMap.get(s1); + ICommand icommand = registry.get(s1); int i = this.getUsernameIndex(icommand, astring); int j = 0; ChatComponentTranslation chatcomponenttranslation; @@ -125,27 +119,12 @@ public ICommand registerCommand(ICommand par1ICommand) { - List list = par1ICommand.getCommandAliases(); - this.commandMap.put(par1ICommand.getCommandName(), par1ICommand); - this.commandSet.add(par1ICommand); + return registry.registerVanillaCommand(par1ICommand); + } - if (list != null) - { - Iterator iterator = list.iterator(); - - while (iterator.hasNext()) - { - String s = (String)iterator.next(); - ICommand icommand1 = (ICommand)this.commandMap.get(s); - - if (icommand1 == null || !icommand1.getCommandName().equals(s)) - { - this.commandMap.put(s, par1ICommand); - } - } - } - - return par1ICommand; + public CommandRegistry getRegistry() + { + return registry; } private static String[] dropFirstString(String[] par0ArrayOfStr) @@ -167,26 +146,13 @@ if (astring.length == 1) { - ArrayList arraylist = new ArrayList(); - Iterator iterator = this.commandMap.entrySet().iterator(); - - while (iterator.hasNext()) - { - Entry entry = (Entry)iterator.next(); - - if (CommandBase.doesStringStartWith(s1, (String)entry.getKey()) && ((ICommand)entry.getValue()).canCommandSenderUseCommand(par1ICommandSender)) - { - arraylist.add(entry.getKey()); - } - } - - return arraylist; + return registry.filterPossibleCommandsNames(par1ICommandSender, s1); } else { if (astring.length > 1) { - ICommand icommand = (ICommand)this.commandMap.get(s1); + ICommand icommand = registry.get(s1); if (icommand != null) { @@ -200,25 +166,12 @@ public List getPossibleCommands(ICommandSender par1ICommandSender) { - ArrayList arraylist = new ArrayList(); - Iterator iterator = this.commandSet.iterator(); - - while (iterator.hasNext()) - { - ICommand icommand = (ICommand)iterator.next(); - - if (icommand.canCommandSenderUseCommand(par1ICommandSender)) - { - arraylist.add(icommand); - } - } - - return arraylist; + return registry.getPossibleCommands(par1ICommandSender); } public Map getCommands() { - return this.commandMap; + return registry.getCommandMap(); } private int getUsernameIndex(ICommand par1ICommand, String[] par2ArrayOfStr) diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java index 3f4ca84..6db220f 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -78,6 +78,7 @@ import org.apache.commons.lang3.Validate; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.ultramine.permission.IPermissionManager; import org.ultramine.server.ConfigurationHandler; import org.ultramine.server.WatchdogThread; import org.ultramine.server.chunk.ChunkIOExecutor; @@ -143,6 +144,7 @@ private static final int TICK_TIME = 1000000000 / TPS; public static double currentTPS = 20; private static long catchupTime = 0; + private IPermissionManager permissionManager; public MinecraftServer(File p_i45281_1_, Proxy p_i45281_2_) { @@ -1433,4 +1435,16 @@ { this.isGamemodeForced = par1; } + + /* ========================================= ULTRAMINE START ======================================*/ + + public IPermissionManager getPermissionManager() + { + return permissionManager; + } + + protected void setPermissionManager(IPermissionManager permissionManager) + { + this.permissionManager = permissionManager; + } } \ No newline at end of file diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java index 7e1eb42..433728e 100644 --- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java @@ -37,6 +37,8 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.ultramine.permission.PermissionRepository; +import org.ultramine.permission.internal.ServerPermissionManager; import org.ultramine.server.ConfigurationHandler; import org.ultramine.server.UltramineServerConfig; import org.ultramine.server.UltramineServerConfig.VanillaConfig; @@ -237,6 +239,7 @@ this.setBuildLimit((this.getBuildLimit() + 8) / 16 * 16); this.setBuildLimit(MathHelper.clamp_int(this.getBuildLimit(), 64, 256)); settings.maxBuildHeight = this.getBuildLimit(); + this.setPermissionManager(new ServerPermissionManager(ConfigurationHandler.getSettingDir(), new PermissionRepository())); // ultramine if (!FMLCommonHandler.instance().handleServerAboutToStart(this)) { return false; } field_155771_h.info("Preparing level \"" + this.getFolderName() + "\""); this.loadAllWorlds(this.getFolderName(), this.getFolderName(), k, worldtype, s2); diff --git a/src/main/java/net/minecraft/server/integrated/IntegratedServer.java b/src/main/java/net/minecraft/server/integrated/IntegratedServer.java index 000207c..62f32ba 100644 --- a/src/main/java/net/minecraft/server/integrated/IntegratedServer.java +++ b/src/main/java/net/minecraft/server/integrated/IntegratedServer.java @@ -28,6 +28,8 @@ import net.minecraftforge.event.world.WorldEvent; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.ultramine.permission.PermissionRepository; +import org.ultramine.permission.internal.ClientPermissionManager; @SideOnly(Side.CLIENT) public class IntegratedServer extends MinecraftServer @@ -88,6 +90,7 @@ this.setAllowFlight(true); logger.info("Generating keypair"); this.setKeyPair(CryptManager.createNewKeyPair()); + this.setPermissionManager(new ClientPermissionManager(getServerOwner(), new PermissionRepository())); // ultramine if (!FMLCommonHandler.instance().handleServerAboutToStart(this)) { return false; } this.loadAllWorlds(this.getFolderName(), this.getWorldName(), this.theWorldSettings.getSeed(), this.theWorldSettings.getTerrainType(), this.theWorldSettings.func_82749_j()); this.setMOTD(this.getServerOwner() + " - " + this.worldServers[0].getWorldInfo().getWorldName()); diff --git a/src/main/java/net/minecraft/server/management/ServerConfigurationManager.java b/src/main/java/net/minecraft/server/management/ServerConfigurationManager.java index 39e5c29..3f79c5b 100644 --- a/src/main/java/net/minecraft/server/management/ServerConfigurationManager.java +++ b/src/main/java/net/minecraft/server/management/ServerConfigurationManager.java @@ -659,23 +659,23 @@ public void addOp(String par1Str) { - PermissionHandler.getInstance().add("global", par1Str, PermissionHandler.OP_PERMISSION); + PermissionHandler.getInstance().add("global", par1Str, OpPermissionProxySet.OP_PERMISSION); } public void removeOp(String par1Str) { - PermissionHandler.getInstance().remove("global", par1Str, PermissionHandler.OP_PERMISSION); + PermissionHandler.getInstance().remove("global", par1Str, OpPermissionProxySet.OP_PERMISSION); } public boolean isAllowedToLogin(String par1Str) { par1Str = par1Str.trim().toLowerCase(); - return !this.whiteListEnforced || PermissionHandler.getInstance().has("global", par1Str, PermissionHandler.OP_PERMISSION) || this.whiteListedPlayers.contains(par1Str); + return !this.whiteListEnforced || PermissionHandler.getInstance().has("global", par1Str, OpPermissionProxySet.OP_PERMISSION) || this.whiteListedPlayers.contains(par1Str); } public boolean isPlayerOpped(String par1Str) { - return PermissionHandler.getInstance().has("global", par1Str, PermissionHandler.OP_PERMISSION) || this.mcServer.isSinglePlayer() && this.mcServer.worldServers[0].getWorldInfo().areCommandsAllowed() && this.mcServer.getServerOwner().equalsIgnoreCase(par1Str) || this.commandsAllowedForAll; + return PermissionHandler.getInstance().has("global", par1Str, OpPermissionProxySet.OP_PERMISSION) || this.mcServer.isSinglePlayer() && this.mcServer.worldServers[0].getWorldInfo().areCommandsAllowed() && this.mcServer.getServerOwner().equalsIgnoreCase(par1Str) || this.commandsAllowedForAll; } public EntityPlayerMP getPlayerForUsername(String par1Str) diff --git a/src/main/java/org/ultramine/commands/Action.java b/src/main/java/org/ultramine/commands/Action.java new file mode 100644 index 0000000..7aac3f6 --- /dev/null +++ b/src/main/java/org/ultramine/commands/Action.java @@ -0,0 +1,14 @@ +package org.ultramine.commands; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface Action +{ + String command(); + String name(); +} diff --git a/src/main/java/org/ultramine/commands/Command.java b/src/main/java/org/ultramine/commands/Command.java new file mode 100644 index 0000000..ceb0cb8 --- /dev/null +++ b/src/main/java/org/ultramine/commands/Command.java @@ -0,0 +1,18 @@ +package org.ultramine.commands; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface Command +{ + public String name(); + public String group(); + public String[] syntax() default {}; + public String[] aliases() default {}; + public String[] permissions() default {}; + public boolean isUsableFromServer() default true; +} \ No newline at end of file diff --git a/src/main/java/org/ultramine/commands/CommandContext.java b/src/main/java/org/ultramine/commands/CommandContext.java new file mode 100644 index 0000000..8e0f8cd --- /dev/null +++ b/src/main/java/org/ultramine/commands/CommandContext.java @@ -0,0 +1,297 @@ +package org.ultramine.commands; + +import net.minecraft.block.Block; +import net.minecraft.command.CommandBase; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; +import net.minecraft.command.WrongUsageException; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.Item; +import net.minecraft.util.IChatComponent; +import org.ultramine.server.PermissionHandler; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class CommandContext +{ + private ICommandSender sender; + private String[] args; + private IExtendedCommand command; + private Map argumentMap; + private int lastArgumentNum; + private String actionName; + private ICommandHandler actionHandler; + + private CommandContext(IExtendedCommand command, ICommandSender sender, String[] args) + { + this.sender = sender; + this.args = args; + this.command = command; + this.argumentMap = new HashMap(args.length); + this.actionName = ""; + this.lastArgumentNum = args.length - 1; + } + + public Argument get(String key) + { + if (!argumentMap.containsKey(key)) + throwBadUsage(); + + return argumentMap.get(key); + } + + public Argument get(int num) + { + if (num < 0 || num >= args.length) + throwBadUsage(); + + return new Argument(num); + } + + public boolean contains(String key) + { + return argumentMap.containsKey(key); + } + + public Argument set(String key, String value) + { + Argument arg = new Argument(value); + argumentMap.put(key, arg); + return arg; + } + + public String getAction() + { + return actionName; + } + + public void doAction() + { + if (actionHandler != null) + actionHandler.processCommand(this); + } + + public ICommandSender getSender() + { + return sender; + } + + public boolean senderIsServer() + { + return sender.getCommandSenderName().equals("Server"); + } + + public EntityPlayerMP getSenderAsPlayer() + { + return CommandBase.getCommandSenderAsPlayer(sender); + } + + public void notifyAdmins(String messageKey, Object... messageArgs) + { + CommandBase.notifyAdmins(sender, messageKey, messageArgs); + } + + public void checkSenderPermission(String permission) + { + if (!senderIsServer() && !PermissionHandler.getInstance().has(sender, permission)) + throw new CommandException("commands.generic.permission"); + } + + public void checkSenderPermissionInWorld(String world, String permission) + { + if (!senderIsServer() && !PermissionHandler.getInstance().has(world, sender.getCommandSenderName(), permission)) + throw new CommandException("commands.generic.permission"); + } + + public void throwBadUsage() + { + throw new WrongUsageException(command.getCommandUsage(sender)); + } + + public String[] getArgs() + { + return args; + } + + public IExtendedCommand getCommand() + { + return command; + } + + public class Argument + { + private int num; + private boolean last; + private String value; + + private Argument(int num) + { + this.value = args[num]; + this.num = num; + this.last = num == lastArgumentNum; + } + + private Argument(int num, boolean last) + { + this.value = args[num]; + this.num = num; + this.last = last; + } + + private Argument(String value) + { + this.value = value; + this.num = -1; + this.last = false; + } + + private String value() + { + return value; + } + + private String[] args() + { + if (num >= 0) + return args; + else + return new String[] {value}; + } + + private int num() + { + return Math.max(num, 0); + } + + public String asString() + { + if (last) + return CommandBase.func_82360_a(sender, args(), num()); + else + return value(); + } + + public Argument[] asArray() + { + if (num < 0) + return new Argument[] {this}; + + Argument[] result = new Argument[args.length - num]; + for (int i = num; i < args.length; i++) + result[i-num] = new Argument(i, false); + return result; + } + + public int asInt() + { + return CommandBase.parseInt(sender, value()); + } + + public int asInt(int minBound) + { + return CommandBase.parseIntWithMin(sender, value(), minBound); + } + + public int asInt(int minBound, int maxBound) + { + return CommandBase.parseIntBounded(sender, value(), minBound, maxBound); + } + + public double asDouble() + { + return CommandBase.parseDouble(sender, value()); + } + + public double asDouble(double minBound) + { + return CommandBase.parseDoubleWithMin(sender, value(), minBound); + } + + public double asDouble(double minBound, double maxBound) + { + return CommandBase.parseDoubleBounded(sender, value(), minBound, maxBound); + } + + public boolean asBoolean() + { + return CommandBase.parseBoolean(sender, value()); + } + + public EntityPlayerMP asPlayer() + { + return CommandBase.getPlayer(sender, value()); + } + + public IChatComponent asChatComponent(boolean emphasizePlayers) + { + return CommandBase.func_147176_a(sender, args(), num(), emphasizePlayers); + } + + public double asCoordinate(double original) + { + return CommandBase.func_110666_a(sender, original, value()); + } + + public double asCoordinate(double original, int minBound, int maxBound) + { + return CommandBase.func_110665_a(sender, original, value(), minBound, maxBound); + } + + public Item asItem() + { + return CommandBase.getItemByText(sender, value()); + } + + public Block asBlock() + { + return CommandBase.getBlockByText(sender, value()); + } + } + + public static class Builder + { + private CommandContext context; + + public Builder(IExtendedCommand command, ICommandSender sender, String[] args) + { + context = new CommandContext(command, sender, args); + } + + public Builder resolveArguments(List names) + { + context.lastArgumentNum = names.size(); + Map nameCount = new HashMap(); + for (int i = 0; i < names.size(); i++) + { + String name = names.get(i); + + if (name == null || name.isEmpty()) + continue; + + if (context.argumentMap.containsKey(name)) + { + Integer count = nameCount.containsKey(name) ? nameCount.get(name) + 1 : 2; + nameCount.put(name, count); + name = name + count.toString(); + } + + context.argumentMap.put(name, context.new Argument(i)); + } + return this; + } + + public Builder setAction(String actionName, ICommandHandler actionHandler) + { + context.actionName = actionName; + context.actionHandler = actionHandler; + return this; + } + + public CommandContext build() + { + return context; + } + } +} diff --git a/src/main/java/org/ultramine/commands/CommandRegistry.java b/src/main/java/org/ultramine/commands/CommandRegistry.java new file mode 100644 index 0000000..b81698b --- /dev/null +++ b/src/main/java/org/ultramine/commands/CommandRegistry.java @@ -0,0 +1,133 @@ +package org.ultramine.commands; + +import net.minecraft.command.CommandBase; +import net.minecraft.command.ICommand; +import net.minecraft.command.ICommandSender; +import org.ultramine.commands.syntax.ArgumentsPatternParser; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.*; + +public class CommandRegistry +{ + private final Map commandMap; + private final SortedSet registeredCommands; + private final ArgumentsPatternParser argumentsPatternParser; + + public CommandRegistry() + { + commandMap = new HashMap(); + registeredCommands = new TreeSet(); + argumentsPatternParser = new ArgumentsPatternParser(); + } + + public IExtendedCommand registerCommand(IExtendedCommand command) + { + List aliases = command.getCommandAliases(); + commandMap.put(command.getCommandName(), command); + registeredCommands.add(command); + + if (aliases != null) + { + for (String alias : aliases) + { + IExtendedCommand cmd = commandMap.get(alias); + if (cmd == null || !cmd.getCommandName().equals(alias)) + commandMap.put(alias, command); + } + } + + return command; + } + + public IExtendedCommand registerVanillaCommand(ICommand command) + { + return registerCommand(new VanillaCommandWrapper(command)); + } + + public void registerCommands(Class cls) + { + List builders = new ArrayList(); + Map> actions = new HashMap>(); + + for (Method method : cls.getMethods()) + { + if (method.isAnnotationPresent(Command.class) && Modifier.isStatic(method.getModifiers())) + { + Command data = method.getAnnotation(Command.class); + HandlerBasedCommand.Builder builder = new HandlerBasedCommand.Builder(data.name(), data.group(), new MethodBasedCommandHandler(method)) + .setAliases(data.aliases()) + .setPermissions(data.permissions()) + .setUsableFromServer(data.isUsableFromServer()); + + for (String completion : data.syntax()) + builder.addArgumentsPattern(argumentsPatternParser.parse(completion)); + + builders.add(builder); + } + + if (method.isAnnotationPresent(Action.class) && Modifier.isStatic(method.getModifiers())) + { + Action data = method.getAnnotation(Action.class); + + if (!actions.containsKey(data.command())) + actions.put(data.command(), new HashMap()); + + actions.get(data.command()).put(data.name(), new MethodBasedCommandHandler(method)); + } + } + + for (HandlerBasedCommand.Builder builder : builders) + { + if (actions.containsKey(builder.getName())) + { + for (Map.Entry action : actions.get(builder.getName()).entrySet()) + builder.addAction(action.getKey(), action.getValue()); + } + + registerCommand(builder.build()); + } + } + + public IExtendedCommand get(String name) + { + return commandMap.get(name); + } + + public Map getCommandMap() + { + return commandMap; + } + + public List filterPossibleCommandsNames(ICommandSender sender, String filter) + { + List result = new ArrayList(); + + for (Map.Entry entry : commandMap.entrySet()) + { + if (CommandBase.doesStringStartWith(filter, entry.getKey()) && entry.getValue().canCommandSenderUseCommand(sender)) + result.add(entry.getKey()); + } + + return result; + } + + public List getPossibleCommands(ICommandSender sender) + { + List result = new ArrayList(); + + for (IExtendedCommand command : registeredCommands) + { + if (command.canCommandSenderUseCommand(sender)) + result.add(command); + } + + return result; + } + + public ArgumentsPatternParser getArgumentsParser() + { + return argumentsPatternParser; + } +} diff --git a/src/main/java/org/ultramine/commands/HandlerBasedCommand.java b/src/main/java/org/ultramine/commands/HandlerBasedCommand.java new file mode 100644 index 0000000..27e55b6 --- /dev/null +++ b/src/main/java/org/ultramine/commands/HandlerBasedCommand.java @@ -0,0 +1,231 @@ +package org.ultramine.commands; + +import net.minecraft.command.ICommandSender; +import net.minecraft.command.WrongUsageException; +import org.apache.commons.lang3.ArrayUtils; +import org.ultramine.commands.syntax.ArgumentsPattern; +import org.ultramine.server.PermissionHandler; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class HandlerBasedCommand implements IExtendedCommand +{ + private String name; + private String usage; + private String group; + private String description; + + private ICommandHandler handler; + private List argumentsPatterns; + private Map actionHandlers; + + private List aliases; + private String[] permissions; + private boolean isUsableFromServer = true; + + public HandlerBasedCommand(String name, String group, ICommandHandler handler) + { + this.name = name; + this.group = group; + this.handler = handler; + this.usage = "command." + name + ".usage"; + this.description = "command." + name + ".description"; + this.argumentsPatterns = new ArrayList(); + this.actionHandlers = new HashMap(); + } + + @Override + public String getCommandName() + { + return name; + } + + @Override + public String getCommandUsage(ICommandSender var1) + { + return usage; + } + + @Override + public String getDescription() + { + return description; + } + + @Override + public String getGroup() + { + return group; + } + + @Override + public List getCommandAliases() + { + return aliases; + } + + @Override + public void processCommand(ICommandSender var1, String[] var2) + { + CommandContext.Builder builder = new CommandContext.Builder(this, var1, var2); + + if (argumentsPatterns.size() > 0) + { + ArgumentsPattern pattern = findArgumentsPattern(var2); + if (pattern == null) + throw new WrongUsageException(usage); + + builder.resolveArguments(pattern.getArgumentsNames()); + + String actionName = pattern.resolveActionName(var2); + if (!actionName.isEmpty()) + builder.setAction(actionName, actionHandlers.get(actionName)); + } + + handler.processCommand(builder.build()); + } + + @Override + public boolean canCommandSenderUseCommand(ICommandSender var1) + { + return (isUsableFromServer && var1.getCommandSenderName().equals("Server")) || PermissionHandler.getInstance().hasAny(var1, permissions); + } + + @Override + public List addTabCompletionOptions(ICommandSender var1, String[] var2) + { + if (argumentsPatterns.size() == 0) + return null; + + List result = null; + Set dupChecker = null; + String[] tail = ArrayUtils.remove(var2, var2.length - 1); + + for (ArgumentsPattern argumentsPattern : argumentsPatterns) + { + ArgumentsPattern.MatchResult currentMatch = argumentsPattern.partialMatch(tail); + + if (currentMatch != ArgumentsPattern.MatchResult.NOT) + { + List options = argumentsPattern.getCompletionOptions(var2); + if (options == null || options.size() == 0) + continue; + + if (result == null) + { + result = options; + } + else + { + if (dupChecker == null) + { + dupChecker = new HashSet(result); + } + + for (String option: options) + { + if (!dupChecker.contains(option)) + { + result.add(option); + dupChecker.add(option); + } + } + } + + if (currentMatch == ArgumentsPattern.MatchResult.FULLY) + break; + } + } + return result; + } + + @Override + public boolean isUsernameIndex(String[] var1, int var2) + { + ArgumentsPattern argumentsPattern = findArgumentsPattern(var1); + return argumentsPattern != null && argumentsPattern.isUsernameIndex(var2); + } + + private ArgumentsPattern findArgumentsPattern(String[] args) + { + if (argumentsPatterns.size() == 0) + return null; + + for (ArgumentsPattern argumentsPattern : argumentsPatterns) + { + if (argumentsPattern.match(args)) + return argumentsPattern; + } + return null; + } + + @Override + public int compareTo(Object o) + { + if (o instanceof IExtendedCommand) + { + int result = getGroup().compareTo(((IExtendedCommand) o).getGroup()); + if (result == 0) + result = getCommandName().compareTo(((IExtendedCommand) o).getCommandName()); + + return result; + } + return -1; + } + + public static class Builder + { + private HandlerBasedCommand command; + + public Builder(String name, String group, ICommandHandler handler) + { + command = new HandlerBasedCommand(name, group, handler); + } + + public String getName() + { + return command.name; + } + + public Builder setAliases(String... aliases) + { + command.aliases = Arrays.asList(aliases); + return this; + } + + public Builder addArgumentsPattern(ArgumentsPattern argumentsPattern) + { + command.argumentsPatterns.add(argumentsPattern); + return this; + } + + public Builder setPermissions(String... permissions) + { + command.permissions = permissions; + return this; + } + + public Builder setUsableFromServer(boolean isUsableFromServer) + { + command.isUsableFromServer = isUsableFromServer; + return this; + } + + public Builder addAction(String name, ICommandHandler action) + { + command.actionHandlers.put(name, action); + return this; + } + + public HandlerBasedCommand build() + { + return command; + } + } +} diff --git a/src/main/java/org/ultramine/commands/ICommandHandler.java b/src/main/java/org/ultramine/commands/ICommandHandler.java new file mode 100644 index 0000000..8f92fc1 --- /dev/null +++ b/src/main/java/org/ultramine/commands/ICommandHandler.java @@ -0,0 +1,6 @@ +package org.ultramine.commands; + +public interface ICommandHandler +{ + public void processCommand(CommandContext context); +} diff --git a/src/main/java/org/ultramine/commands/IExtendedCommand.java b/src/main/java/org/ultramine/commands/IExtendedCommand.java new file mode 100644 index 0000000..538195c --- /dev/null +++ b/src/main/java/org/ultramine/commands/IExtendedCommand.java @@ -0,0 +1,9 @@ +package org.ultramine.commands; + +import net.minecraft.command.ICommand; + +public interface IExtendedCommand extends ICommand +{ + public String getDescription(); + public String getGroup(); +} \ No newline at end of file diff --git a/src/main/java/org/ultramine/commands/MethodBasedCommandHandler.java b/src/main/java/org/ultramine/commands/MethodBasedCommandHandler.java new file mode 100644 index 0000000..e0718af --- /dev/null +++ b/src/main/java/org/ultramine/commands/MethodBasedCommandHandler.java @@ -0,0 +1,46 @@ +package org.ultramine.commands; + +import net.minecraft.command.CommandException; +import net.minecraft.command.CommandNotFoundException; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +public class MethodBasedCommandHandler implements ICommandHandler +{ + private static final Logger logger = LogManager.getLogger(); + private Method method; + + public MethodBasedCommandHandler(Method method) + { + this.method = method; + } + + @Override + public void processCommand(CommandContext context) + { + try + { + method.invoke(null, context); + } + catch (IllegalAccessException e) + { + logger.error("Error while executing method for command " + context.getCommand().getCommandName(), e); + throw new CommandNotFoundException(); + } + catch (InvocationTargetException e) + { + if (e.getCause() == null) + { + logger.error("Error while executing method for command " + context.getCommand().getCommandName(), e); + throw new CommandNotFoundException(); + } + else if (e.getCause() instanceof CommandException) + throw (CommandException) e.getCause(); + else + throw new RuntimeException("Error while executing method for command " + context.getCommand().getCommandName(), e.getCause()); + } + } +} diff --git a/src/main/java/org/ultramine/commands/VanillaCommandWrapper.java b/src/main/java/org/ultramine/commands/VanillaCommandWrapper.java new file mode 100644 index 0000000..0042803 --- /dev/null +++ b/src/main/java/org/ultramine/commands/VanillaCommandWrapper.java @@ -0,0 +1,89 @@ +package org.ultramine.commands; + +import net.minecraft.command.ICommand; +import net.minecraft.command.ICommandSender; +import org.ultramine.server.PermissionHandler; + +import java.util.List; + +public class VanillaCommandWrapper implements IExtendedCommand +{ + private ICommand wrappedCommand; + private String permission; + private String description; + + public VanillaCommandWrapper(ICommand wrappedCommand) + { + this.wrappedCommand = wrappedCommand; + this.permission = "command.vanilla." + wrappedCommand.getCommandName(); + this.description = "command." + wrappedCommand.getCommandName() + ".description"; + } + + @Override + public String getCommandName() + { + return wrappedCommand.getCommandName(); + } + + @Override + public String getCommandUsage(ICommandSender var1) + { + return wrappedCommand.getCommandUsage(var1); + } + + @Override + public List getCommandAliases() + { + return wrappedCommand.getCommandAliases(); + } + + @Override + public void processCommand(ICommandSender var1, String[] var2) + { + wrappedCommand.processCommand(var1, var2); + } + + @Override + public boolean canCommandSenderUseCommand(ICommandSender var1) + { + return (var1.getCommandSenderName().equals("Server") || PermissionHandler.getInstance().has(var1, permission)) && wrappedCommand.canCommandSenderUseCommand(var1); + } + + @Override + public List addTabCompletionOptions(ICommandSender var1, String[] var2) + { + return wrappedCommand.addTabCompletionOptions(var1, var2); + } + + @Override + public boolean isUsernameIndex(String[] var1, int var2) + { + return wrappedCommand.isUsernameIndex(var1, var2); + } + + @Override + public int compareTo(Object o) + { + if (o instanceof IExtendedCommand) + { + int result = getGroup().compareTo(((IExtendedCommand) o).getGroup()); + if (result == 0) + result = getCommandName().compareTo(((IExtendedCommand) o).getCommandName()); + + return result; + } + return -1; + } + + @Override + public String getDescription() + { + return description; + } + + @Override + public String getGroup() + { + return "vanilla"; + } +} diff --git a/src/main/java/org/ultramine/commands/syntax/ArgumentCompleter.java b/src/main/java/org/ultramine/commands/syntax/ArgumentCompleter.java new file mode 100644 index 0000000..8b39205 --- /dev/null +++ b/src/main/java/org/ultramine/commands/syntax/ArgumentCompleter.java @@ -0,0 +1,14 @@ +package org.ultramine.commands.syntax; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface ArgumentCompleter +{ + String value(); + boolean isUsername() default false; +} \ No newline at end of file diff --git a/src/main/java/org/ultramine/commands/syntax/ArgumentValidator.java b/src/main/java/org/ultramine/commands/syntax/ArgumentValidator.java new file mode 100644 index 0000000..2618467 --- /dev/null +++ b/src/main/java/org/ultramine/commands/syntax/ArgumentValidator.java @@ -0,0 +1,13 @@ +package org.ultramine.commands.syntax; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface ArgumentValidator +{ + String value(); +} diff --git a/src/main/java/org/ultramine/commands/syntax/ArgumentsPattern.java b/src/main/java/org/ultramine/commands/syntax/ArgumentsPattern.java new file mode 100644 index 0000000..5357fbb --- /dev/null +++ b/src/main/java/org/ultramine/commands/syntax/ArgumentsPattern.java @@ -0,0 +1,204 @@ +package org.ultramine.commands.syntax; + +import net.minecraft.command.CommandBase; + +import java.util.ArrayList; +import java.util.List; + +public class ArgumentsPattern +{ + private final List arguments; + private final List names; + private final List actionPositions; + private boolean isInfinite; + + private ArgumentsPattern() + { + arguments = new ArrayList(); + names = new ArrayList(); + actionPositions = new ArrayList(); + isInfinite = false; + } + + private IArgument getSafe(int num) + { + if (num >= arguments.size()) + return isInfinite ? arguments.get(arguments.size() - 1) : IGNORED; + else + return arguments.get(num); + } + + public List getCompletionOptions(String[] args) + { + if (arguments.size() == 0) + return null; + + return getSafe(args.length - 1).getCompletionOptions(args); + } + + public boolean isUsernameIndex(int checkArgNum) + { + return getSafe(checkArgNum).isUsername(); + } + + public boolean match(String[] args) + { + for (int i = 0; i < args.length; i++) + { + if (i == arguments.size()) + return isInfinite; + + IArgument argument = arguments.get(i); + if (argument.hasValidation() && !argument.validate(args[i])) + return false; + } + return args.length == arguments.size(); + } + + public MatchResult partialMatch(String[] args) + { + for (int i = 0; i < arguments.size(); i++) + { + IArgument argument = arguments.get(i); + + if (i < args.length) + { + if (argument.hasValidation() && !argument.validate(args[i])) + return MatchResult.NOT; + } + else + { + if (argument.hasValidation()) + return MatchResult.POSSIBLY; + } + } + if (isInfinite || args.length <= arguments.size()) + return MatchResult.FULLY; + else + return MatchResult.NOT; + } + + public List getArgumentsNames() + { + return names; + } + + public String resolveActionName(String[] args) + { + if (actionPositions.size() == 0) + return ""; + + StringBuilder builder = new StringBuilder(args[actionPositions.get(0)]); + for (int i = 1; i < actionPositions.size(); i++) + builder.append(' ').append(args[actionPositions.get(i)]); + + return builder.toString(); + } + + public static class Builder + { + private ArgumentsPattern pattern; + + public Builder() + { + pattern = new ArgumentsPattern(); + } + + public void addArgument(String name, IArgument argument) + { + pattern.arguments.add(argument); + pattern.names.add(name); + } + + public void addAction(String[] options) + { + pattern.actionPositions.add(pattern.arguments.size()); + addArgument(null, new ActionArgument(options)); + } + + public void makeInfinite() + { + pattern.isInfinite = true; + } + + public ArgumentsPattern build() + { + return pattern; + } + } + + private static class ActionArgument implements IArgument + { + private final String[] options; + + private ActionArgument(String[] options) + { + this.options = options; + } + + @Override + public boolean isUsername() + { + return false; + } + + @Override + public List getCompletionOptions(String[] args) + { + List result = new ArrayList(); + String val = args[args.length - 1]; + for (String option : options) + { + if (CommandBase.doesStringStartWith(val, option)) + result.add(option); + } + return result; + } + + @Override + public boolean hasValidation() + { + return true; + } + + @Override + public boolean validate(String val) + { + for (String action : options) + { + if (action.equalsIgnoreCase(val)) + return true; + } + return false; + } + } + + public static final IArgument IGNORED = new IArgument() + { + @Override + public boolean isUsername() + { + return false; + } + + @Override + public List getCompletionOptions(String[] args) + { + return null; + } + + @Override + public boolean hasValidation() + { + return false; + } + + @Override + public boolean validate(String val) + { + return true; + } + }; + + public static enum MatchResult { FULLY, POSSIBLY, NOT } +} diff --git a/src/main/java/org/ultramine/commands/syntax/ArgumentsPatternParser.java b/src/main/java/org/ultramine/commands/syntax/ArgumentsPatternParser.java new file mode 100644 index 0000000..9b43423 --- /dev/null +++ b/src/main/java/org/ultramine/commands/syntax/ArgumentsPatternParser.java @@ -0,0 +1,181 @@ +package org.ultramine.commands.syntax; + +import org.apache.commons.lang3.StringUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class ArgumentsPatternParser +{ + private static final Logger logger = LogManager.getLogger(); + + private static final Pattern argumentPattern = Pattern.compile("([\\[<])\\s*(([^<>%\\[\\]\\s]*)\\s*([^<>%\\[\\]]*))(|%\\s*([^<>%\\[\\]\\s]*)\\s*)[\\]>]"); + + private final Map completionHandlers = new HashMap(); + private final Map validationHandlers = new HashMap(); + private final List arguments = new ArrayList(); + + public ArgumentsPattern parse(String completionString) + { + ArgumentsPattern.Builder builder = new ArgumentsPattern.Builder(); + Matcher matcher = argumentPattern.matcher(completionString); + + while (matcher.find()) + { + if (matcher.group(1).equals("[")) + { + String[] params = StringUtils.split(matcher.group(2)); + builder.addAction(params); + } + else + { + String handlerName = matcher.group(3); + String argumentName = matcher.group(6); + if (argumentName == null || argumentName.isEmpty()) + argumentName = handlerName; + + String[] params = StringUtils.split(matcher.group(4)); + HandlerBasedArgument argument = new HandlerBasedArgument(argumentName, params); + argument.setValidationHandler(validationHandlers.get(argumentName)); + argument.setCompletionHandler(completionHandlers.get(argumentName)); + arguments.add(argument); + builder.addArgument(argumentName, argument); + } + } + + if (completionString.endsWith("...")) + builder.makeInfinite(); + + return builder.build(); + } + + public void registerHandler(String name, IArgumentCompletionHandler handler) + { + registerHandlerDelayed(name, handler); + updateArguments(); + } + + public void registerHandler(String name, IArgumentValidationHandler handler) + { + registerHandlerDelayed(name, handler); + updateArguments(); + } + + public void registerHandlers(Class cls) + { + for (Method handler : cls.getMethods()) + { + if (!Modifier.isStatic(handler.getModifiers())) + continue; + + if (handler.isAnnotationPresent(ArgumentCompleter.class)) + { + ArgumentCompleter data = handler.getAnnotation(ArgumentCompleter.class); + registerHandlerDelayed(data.value(), new WrappedCompletionHandler(handler, data.isUsername())); + } + + if (handler.isAnnotationPresent(ArgumentValidator.class)) + { + ArgumentValidator data = handler.getAnnotation(ArgumentValidator.class); + registerHandlerDelayed(data.value(), new WrappedValidationHandler(handler)); + } + } + updateArguments(); + } + + private void registerHandlerDelayed(String name, IArgumentCompletionHandler handler) + { + if (!completionHandlers.containsKey(name)) + completionHandlers.put(name, handler); + else + logger.warn("Completion handler name is already registered: " + name); + } + + private void registerHandlerDelayed(String name, IArgumentValidationHandler handler) + { + if (!validationHandlers.containsKey(name)) + validationHandlers.put(name, handler); + else + logger.warn("Validation handler name is already registered: " + name); + } + + private void updateArguments() + { + for (HandlerBasedArgument argument : arguments) + { + argument.setCompletionHandler(completionHandlers.get(argument.getName())); + argument.setValidationHandler(validationHandlers.get(argument.getName())); + } + } + + private static class WrappedCompletionHandler implements IArgumentCompletionHandler + { + private Method method; + private boolean isUsername; + + private WrappedCompletionHandler(Method method, boolean isUsername) + { + this.method = method; + this.isUsername = isUsername; + } + + @Override + public List handleCompletion(String val, String[] params) + { + try + { + return (List) method.invoke(null, val, params); + } + catch (IllegalAccessException ignored) + { + } + catch (InvocationTargetException ignored) + { + } + + return null; + } + + @Override + public boolean isUsername() + { + return isUsername; + } + } + + private static class WrappedValidationHandler implements IArgumentValidationHandler + { + private Method method; + + private WrappedValidationHandler(Method method) + { + this.method = method; + } + + @Override + public boolean handleValidation(String val, String[] params) + { + try + { + return (Boolean) method.invoke(null, val, params); + } + catch (IllegalAccessException ignored) + { + } + catch (InvocationTargetException ignored) + { + } + + return true; + } + } +} diff --git a/src/main/java/org/ultramine/commands/syntax/DefaultCompleters.java b/src/main/java/org/ultramine/commands/syntax/DefaultCompleters.java new file mode 100644 index 0000000..0fe36d4 --- /dev/null +++ b/src/main/java/org/ultramine/commands/syntax/DefaultCompleters.java @@ -0,0 +1,69 @@ +package org.ultramine.commands.syntax; + +import net.minecraft.block.Block; +import net.minecraft.command.CommandBase; +import net.minecraft.entity.EntityList; +import net.minecraft.item.Item; +import net.minecraft.server.MinecraftServer; + +import java.util.ArrayList; +import java.util.List; + +public class DefaultCompleters +{ + @ArgumentCompleter(value = "player", isUsername = true) + public static List player(String val, String[] args) + { + return filterArray(val, MinecraftServer.getServer().getAllUsernames()); + } + + @ArgumentCompleter("item") + public static List item(String val, String[] args) + { + return filterCollection(val, Item.itemRegistry.getKeys()); + } + + @ArgumentCompleter("block") + public static List block(String val, String[] args) + { + return filterCollection(val, Block.blockRegistry.getKeys()); + } + + @ArgumentCompleter("entity") + public static List entity(String val, String[] args) + { + return filterCollection(val, EntityList.func_151515_b()); + } + + @ArgumentCompleter("list") + public static List list(String val, String[] args) + { + return filterArray(val, args); + } + + public static List filterArray(String filter, String[] strings) + { + List result = new ArrayList(); + + for (String str : strings) + { + if (CommandBase.doesStringStartWith(filter, str)) + result.add(str); + } + + return result; + } + + public static List filterCollection(String filter, Iterable iterable) + { + List result = new ArrayList(); + + for (String str : iterable) + { + if (CommandBase.doesStringStartWith(filter, str)) + result.add(str); + } + + return result; + } +} diff --git a/src/main/java/org/ultramine/commands/syntax/HandlerBasedArgument.java b/src/main/java/org/ultramine/commands/syntax/HandlerBasedArgument.java new file mode 100644 index 0000000..6c5faaf --- /dev/null +++ b/src/main/java/org/ultramine/commands/syntax/HandlerBasedArgument.java @@ -0,0 +1,95 @@ +package org.ultramine.commands.syntax; + +import java.util.List; + +public class HandlerBasedArgument implements IArgument +{ + private IArgumentCompletionHandler completionHandler; + private IArgumentValidationHandler validationHandler; + private final String name; + private final String[] params; + private int[] links; + + public HandlerBasedArgument(String name, String[] params) { + this.name = name; + this.params = new String[params.length]; + this.links = new int[params.length]; + boolean hasLinks = false; + + for (int i = 0; i < params.length; i++) + { + String param = params[i]; + if (param.startsWith("&")) + { + try + { + int argNum = Integer.valueOf(param.substring(1)); + this.links[i] = argNum; + this.params[i] = ""; + hasLinks = true; + continue; + } + catch (Exception ignored) {} + } + this.links[i] = -1; + this.params[i] = param; + } + + if (!hasLinks) links = null; + } + + public void setCompletionHandler(IArgumentCompletionHandler completionHandler) + { + this.completionHandler = completionHandler; + } + + public void setValidationHandler(IArgumentValidationHandler validationHandler) + { + this.validationHandler = validationHandler; + } + + public String getName() + { + return name; + } + + @Override + public boolean isUsername() + { + return completionHandler != null && completionHandler.isUsername(); + } + + @Override + public List getCompletionOptions(String[] args) + { + if (completionHandler == null) + return null; + + String[] params; + if (links != null) + { + params = new String[this.params.length]; + for (int i = 0; i < this.params.length; i++) + { + int link = links[i]; + params[i] = link >= 0 && link < args.length ? args[link] : this.params[i]; + } + } + else + params = this.params; + + return completionHandler.handleCompletion(args[args.length - 1], params); + } + + @Override + public boolean hasValidation() + { + return validationHandler != null; + } + + @Override + public boolean validate(String val) + { + return validationHandler == null || validationHandler.handleValidation(val, params); + } +} diff --git a/src/main/java/org/ultramine/commands/syntax/IArgument.java b/src/main/java/org/ultramine/commands/syntax/IArgument.java new file mode 100644 index 0000000..23b5727 --- /dev/null +++ b/src/main/java/org/ultramine/commands/syntax/IArgument.java @@ -0,0 +1,12 @@ +package org.ultramine.commands.syntax; + +import java.util.List; + +interface IArgument +{ + boolean isUsername(); + List getCompletionOptions(String[] args); + + boolean hasValidation(); + boolean validate(String val); +} \ No newline at end of file diff --git a/src/main/java/org/ultramine/commands/syntax/IArgumentCompletionHandler.java b/src/main/java/org/ultramine/commands/syntax/IArgumentCompletionHandler.java new file mode 100644 index 0000000..af65bc4 --- /dev/null +++ b/src/main/java/org/ultramine/commands/syntax/IArgumentCompletionHandler.java @@ -0,0 +1,9 @@ +package org.ultramine.commands.syntax; + +import java.util.List; + +public interface IArgumentCompletionHandler +{ + List handleCompletion(String val, String[] params); + boolean isUsername(); +} \ No newline at end of file diff --git a/src/main/java/org/ultramine/commands/syntax/IArgumentValidationHandler.java b/src/main/java/org/ultramine/commands/syntax/IArgumentValidationHandler.java new file mode 100644 index 0000000..95daec5 --- /dev/null +++ b/src/main/java/org/ultramine/commands/syntax/IArgumentValidationHandler.java @@ -0,0 +1,6 @@ +package org.ultramine.commands.syntax; + +public interface IArgumentValidationHandler +{ + boolean handleValidation(String val, String[] params); +} \ No newline at end of file diff --git a/src/main/java/org/ultramine/permission/ClientPermissionManager.java b/src/main/java/org/ultramine/permission/ClientPermissionManager.java deleted file mode 100644 index 843b9db..0000000 --- a/src/main/java/org/ultramine/permission/ClientPermissionManager.java +++ /dev/null @@ -1,91 +0,0 @@ -package org.ultramine.permission; - -import java.util.Set; - -public class ClientPermissionManager implements IPermissionHandler -{ - private World global; - private PermissionRepository permissionRepository; - - public ClientPermissionManager(PermissionRepository permissionRepository) - { - this.permissionRepository = permissionRepository; - this.global = new World(permissionRepository); - } - - @Override - public boolean has(String world, String player, String permission) - { - return global.checkUserPermission(player, permission); - } - - @Override - public void add(String world, String player, String permission) - { - if (!global.contains(player)) - global.add(new User(player)); - - global.get(player).addPermission(permissionRepository.getPermission(permission)); - } - - @Override - public void add(String world, String permission) - { - global.getDefaultPermissions().addPermission(permissionRepository.getPermission(permission)); - } - - @Override - public void remove(String world, String player, String permission) - { - if (!global.contains(player)) - return; - - global.get(player).removePermission(permission); - } - - @Override - public void remove(String world, String permission) - { - global.getDefaultPermissions().removePermission(permission); - } - - @Override - public MetaResolver getMeta(String world, String player) - { - if (!global.contains(player)) - return MetaResolver.BLANK_RESOLVER; - - return global.get(player).getMeta(); - } - - @Override - public void setMeta(String world, String player, String key, Object value) - { - if (!global.contains(player)) - global.add(new User(player)); - - global.get(player).setMeta(key, value); - } - - @Override - public Set findUsersWithPermission(String world, String permission) - { - return global.getAllWithPermission(permission); - } - - @Override - public void save() - { - } - - @Override - public void reload() - { - } - - @Override - public PermissionRepository getRepository() - { - return permissionRepository; - } -} diff --git a/src/main/java/org/ultramine/permission/DummyPermission.java b/src/main/java/org/ultramine/permission/DummyPermission.java new file mode 100644 index 0000000..b184024 --- /dev/null +++ b/src/main/java/org/ultramine/permission/DummyPermission.java @@ -0,0 +1,83 @@ +package org.ultramine.permission; + +import org.ultramine.permission.internal.CheckResult; +import org.ultramine.permission.internal.MetaResolver; +import org.ultramine.permission.internal.PermissionResolver; + +public class DummyPermission implements IPermission +{ + private String key; + + public DummyPermission(String key) + { + this.key = key.toLowerCase(); + } + + @Override + public String getKey() + { + return key; + } + + @Override + public CheckResult check(String key) + { + if (key == null) + return CheckResult.UNRESOLVED; + + key = key.toLowerCase(); + if (key.equals(getKey()) || "*".equals(getKey())) + return CheckResult.TRUE; + + if (getKey().endsWith(".*")) + { + String base = getKey().substring(0, getKey().length() - 3); + if (key.startsWith(base)) + return CheckResult.TRUE; + } + + return CheckResult.UNRESOLVED; + } + + @Override + public String getMeta(String key) + { + return ""; + } + + @Override + public void mergePermissionsTo(PermissionResolver resolver) + { + resolver.merge(getKey(), (Boolean)true, Integer.MAX_VALUE); + } + + @Override + public void mergeMetaTo(MetaResolver resolver) + { + } + + @Override + public void subscribe(IDirtyListener listener) + { + } + + @Override + public void unsubscribe(IDirtyListener listener) + { + } + + @Override + public int hashCode() + { + return getKey().hashCode(); + } + + @Override + public boolean equals(Object obj) + { + if (obj instanceof IPermission) + return getKey().equals(((IPermission)obj).getKey()); + + return super.equals(obj); + } +} diff --git a/src/main/java/org/ultramine/permission/GroupPermission.java b/src/main/java/org/ultramine/permission/GroupPermission.java index 6f9ed11..c28ff2b 100644 --- a/src/main/java/org/ultramine/permission/GroupPermission.java +++ b/src/main/java/org/ultramine/permission/GroupPermission.java @@ -1,10 +1,14 @@ package org.ultramine.permission; +import org.ultramine.permission.internal.MetaResolver; +import org.ultramine.permission.internal.PermissionHolder; +import org.ultramine.permission.internal.PermissionResolver; + import java.util.ArrayList; import java.util.List; import java.util.Map; -public class GroupPermission extends PermissionHolder implements IChangeablePermission +public class GroupPermission extends PermissionHolder implements IPermission { private final String key; private final List listeners = new ArrayList(); @@ -15,7 +19,7 @@ this.key = key.toLowerCase(); } - public GroupPermission(String key, Map meta) + public GroupPermission(String key, Map meta) { super(meta); this.key = key.toLowerCase(); @@ -28,21 +32,15 @@ } @Override - public String getName() + public void mergePermissionsTo(PermissionResolver resolver) { - if (innerMeta.containsKey("name")) - return (String) innerMeta.get("name"); - else - return key; + resolver.merge(getPermissionResolver(), getPriority()); } @Override - public String getDescription() + public void mergeMetaTo(MetaResolver resolver) { - if (innerMeta.containsKey("description")) - return (String) innerMeta.get("description"); - else - return ""; + resolver.merge(getMetaResolver(), getPriority()); } @Override @@ -68,6 +66,11 @@ listener.makeDirty(); } + private int getPriority() + { + return getMetaResolver().getInt("priority"); + } + @Override public int hashCode() { diff --git a/src/main/java/org/ultramine/permission/IChangeablePermission.java b/src/main/java/org/ultramine/permission/IChangeablePermission.java deleted file mode 100644 index cad4c8c..0000000 --- a/src/main/java/org/ultramine/permission/IChangeablePermission.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.ultramine.permission; - -public interface IChangeablePermission extends IPermission -{ - public void subscribe(IDirtyListener listener); - public void unsubscribe(IDirtyListener listener); -} diff --git a/src/main/java/org/ultramine/permission/IPermission.java b/src/main/java/org/ultramine/permission/IPermission.java index 4179247..584daf5 100644 --- a/src/main/java/org/ultramine/permission/IPermission.java +++ b/src/main/java/org/ultramine/permission/IPermission.java @@ -1,12 +1,18 @@ package org.ultramine.permission; +import org.ultramine.permission.internal.CheckResult; +import org.ultramine.permission.internal.MetaResolver; +import org.ultramine.permission.internal.PermissionResolver; + public interface IPermission { public String getKey(); - public String getName(); - public String getDescription(); - public int getPriority(); + public CheckResult check(String key); + public String getMeta(String key); - public PermissionResolver getPermissions(); - public MetaResolver getMeta(); + public void mergePermissionsTo(PermissionResolver resolver); + public void mergeMetaTo(MetaResolver resolver); + + public void subscribe(IDirtyListener listener); + public void unsubscribe(IDirtyListener listener); } \ No newline at end of file diff --git a/src/main/java/org/ultramine/permission/IPermissionHandler.java b/src/main/java/org/ultramine/permission/IPermissionHandler.java deleted file mode 100644 index 129e779..0000000 --- a/src/main/java/org/ultramine/permission/IPermissionHandler.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.ultramine.permission; - -import java.util.Set; - -public interface IPermissionHandler -{ - public boolean has(String world, String player, String permission); - - public void add(String world, String player, String permission); - - public void add(String world, String permission); - - public void remove(String world, String player, String permission); - - public void remove(String world, String permission); - - public MetaResolver getMeta(String world, String player); - - public void setMeta(String world, String player, String key, Object value); - - public Set findUsersWithPermission(String world, String permission); - - public void save(); - - public void reload(); - - public PermissionRepository getRepository(); -} \ No newline at end of file diff --git a/src/main/java/org/ultramine/permission/IPermissionManager.java b/src/main/java/org/ultramine/permission/IPermissionManager.java new file mode 100644 index 0000000..37cd173 --- /dev/null +++ b/src/main/java/org/ultramine/permission/IPermissionManager.java @@ -0,0 +1,34 @@ +package org.ultramine.permission; + +import org.ultramine.permission.internal.UserContainer; + +public interface IPermissionManager +{ + public boolean has(String world, String player, String permission); + + public void add(String world, String player, String permission); + + public void addToWorld(String world, String permission); + + public void addToGroup(String group, String permission); + + public void remove(String world, String player, String permission); + + public void removeFromWorld(String world, String permission); + + public void removeFromGroup(String group, String permission); + + public String getMeta(String world, String player, String key); + + public void setMeta(String world, String player, String key, String value); + + public void setGroupMeta(String group, String key, String value); + + public void save(); + + public void reload(); + + public PermissionRepository getRepository(); + + public UserContainer getWorldContainer(String world); +} \ No newline at end of file diff --git a/src/main/java/org/ultramine/permission/MetaHolder.java b/src/main/java/org/ultramine/permission/MetaHolder.java deleted file mode 100644 index 9ff56e4..0000000 --- a/src/main/java/org/ultramine/permission/MetaHolder.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.ultramine.permission; - -import java.util.HashMap; -import java.util.Map; - -public abstract class MetaHolder -{ - protected Map innerMeta; - - public MetaHolder() - { - innerMeta = new HashMap(); - } - - public MetaHolder(Map meta) - { - setInnerMeta(meta); - } - - public void setMeta(String key, Object value) - { - innerMeta.put(key, value); - } - - public void removeMeta(String key) - { - innerMeta.remove(key); - } - - public void clearMeta() - { - innerMeta.clear(); - } - - public int getPriority() - { - return getMeta().getInt("priority"); - } - - public Map getInnerMeta() - { - return new HashMap(innerMeta); - } - - public void setInnerMeta(Map meta) - { - innerMeta = new HashMap(meta); - } - - public abstract MetaResolver getMeta(); -} diff --git a/src/main/java/org/ultramine/permission/MetaResolver.java b/src/main/java/org/ultramine/permission/MetaResolver.java deleted file mode 100644 index 73836da..0000000 --- a/src/main/java/org/ultramine/permission/MetaResolver.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.ultramine.permission; - -public class MetaResolver extends Resolver -{ - public static final MetaResolver BLANK_RESOLVER = new MetaResolver(); - - public String getString(String key) - { - if (values.containsKey(key)) - return (String)values.get(key); - else - return ""; - } - - public int getInt(String key) - { - if (values.containsKey(key)) - return (Integer)values.get(key); - else - return 0; - } - - -} diff --git a/src/main/java/org/ultramine/permission/NegativePermission.java b/src/main/java/org/ultramine/permission/NegativePermission.java index aa1b0f0..bc59143 100644 --- a/src/main/java/org/ultramine/permission/NegativePermission.java +++ b/src/main/java/org/ultramine/permission/NegativePermission.java @@ -1,58 +1,52 @@ package org.ultramine.permission; -public class NegativePermission extends PermissionRepository.ProxyPermission implements IDirtyListener -{ - private PermissionResolver resolver; - private boolean dirty; +import org.ultramine.permission.internal.CheckResult; +import org.ultramine.permission.internal.MetaResolver; +import org.ultramine.permission.internal.PermissionResolver; - public NegativePermission(IPermission permission) +class NegativePermission extends PermissionRepository.ProxyPermission +{ + private String key; + + public NegativePermission(String key, IPermission permission) { super(permission); - super.subscribe(this); - this.dirty = true; + this.key = key; } @Override public String getKey() { - return "^" + super.getKey(); + return key; } @Override - public String getName() + public CheckResult check(String key) { - return "NOT: " + super.getName(); + return super.check(key).invert(); } @Override - public String getDescription() + public String getMeta(String key) { - if (!super.getDescription().isEmpty()) - return "NOT: " + super.getDescription(); - else - return ""; + return ""; } @Override - public PermissionResolver getPermissions() + public void mergePermissionsTo(final PermissionResolver resolver) { - if (dirty) + super.mergePermissionsTo(new PermissionResolver() { - resolver = PermissionResolver.createInverted(super.getPermissions()); - dirty = false; - } - return resolver; + @Override + public boolean merge(String key, Boolean value, int priority) + { + return resolver.merge(key, !value, priority); + } + }); } @Override - public MetaResolver getMeta() + public void mergeMetaTo(MetaResolver resolver) { - return MetaResolver.BLANK_RESOLVER; - } - - @Override - public void makeDirty() - { - dirty = true; } } diff --git a/src/main/java/org/ultramine/permission/Permission.java b/src/main/java/org/ultramine/permission/Permission.java deleted file mode 100644 index f4be49f..0000000 --- a/src/main/java/org/ultramine/permission/Permission.java +++ /dev/null @@ -1,73 +0,0 @@ -package org.ultramine.permission; - -public class Permission implements IPermission -{ - private String key; - private String name; - private String description; - private PermissionResolver resolver; - - public Permission(String key, String name, String description) - { - this.key = key.toLowerCase(); - this.name = name; - this.description = description; - this.resolver = PermissionResolver.createForKey(key, getPriority()); - } - - public Permission(String key) - { - this(key, key, ""); - } - - @Override - public String getKey() - { - return key; - } - - @Override - public String getName() - { - return name; - } - - @Override - public String getDescription() - { - return description; - } - - @Override - public int getPriority() - { - return Integer.MAX_VALUE; - } - - @Override - public PermissionResolver getPermissions() - { - return resolver; - } - - @Override - public MetaResolver getMeta() - { - return MetaResolver.BLANK_RESOLVER; - } - - @Override - public int hashCode() - { - return getKey().hashCode(); - } - - @Override - public boolean equals(Object obj) - { - if (obj instanceof IPermission) - return getKey().equals(((IPermission)obj).getKey()); - - return super.equals(obj); - } -} diff --git a/src/main/java/org/ultramine/permission/PermissionHolder.java b/src/main/java/org/ultramine/permission/PermissionHolder.java deleted file mode 100644 index bdb3971..0000000 --- a/src/main/java/org/ultramine/permission/PermissionHolder.java +++ /dev/null @@ -1,139 +0,0 @@ -package org.ultramine.permission; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class PermissionHolder extends MetaHolder implements IDirtyListener -{ - private boolean dirty; - - private Map permissions = new HashMap(); - private PermissionResolver permissionResolver = new PermissionResolver(); - private MetaResolver metaResolver = new MetaResolver(); - - public PermissionHolder() - { - super(); - this.dirty = false; - } - - public PermissionHolder(Map meta) - { - super(meta); - this.dirty = true; - } - - public PermissionResolver getPermissions() - { - if (isDirty()) - calculate(); - - return permissionResolver; - } - - @Override - public MetaResolver getMeta() - { - if (isDirty()) - calculate(); - - return metaResolver; - } - - public void addPermission(IPermission permission) - { - if (permissions.containsKey(permission.getKey())) - return; - - permissions.put(permission.getKey(), permission); - if (permission instanceof IChangeablePermission) - ((IChangeablePermission) permission).subscribe(this); - - makeDirty(); - } - - public void removePermission(IPermission permission) - { - removePermission(permission.getKey()); - } - - public void removePermission(String key) - { - if (!permissions.containsKey(key)) - return; - - IPermission perm = permissions.remove(key); - if (perm instanceof IChangeablePermission) - ((IChangeablePermission) perm).unsubscribe(this); - - makeDirty(); - } - - public void clearPermissions() - { - for (IPermission perm : permissions.values()) - { - if (perm instanceof IChangeablePermission) - ((IChangeablePermission) perm).unsubscribe(this); - } - permissions.clear(); - makeDirty(); - } - - public List getInnerPermissions() - { - return new ArrayList(permissions.keySet()); - } - - public boolean isDirty() - { - return dirty; - } - - @Override - public void makeDirty() - { - dirty = true; - } - - @Override - public void setMeta(String key, Object value) - { - super.setMeta(key, value); - makeDirty(); - } - - @Override - public void removeMeta(String key) - { - super.removeMeta(key); - makeDirty(); - } - - @Override - public void clearMeta() - { - super.clearMeta(); - makeDirty(); - } - - public void calculate() - { - if (!isDirty()) - return; - dirty = false; - - permissionResolver.clear(); - metaResolver.clear(); - - for (IPermission permission : permissions.values()) - { - permissionResolver.merge(permission.getPermissions(), permission.getPriority()); - metaResolver.merge(permission.getMeta(), permission.getPriority()); - } - - metaResolver.merge(innerMeta, Integer.MAX_VALUE); - } -} diff --git a/src/main/java/org/ultramine/permission/PermissionRepository.java b/src/main/java/org/ultramine/permission/PermissionRepository.java index 744bd50..807aed0 100644 --- a/src/main/java/org/ultramine/permission/PermissionRepository.java +++ b/src/main/java/org/ultramine/permission/PermissionRepository.java @@ -1,26 +1,25 @@ package org.ultramine.permission; +import org.ultramine.permission.internal.CheckResult; +import org.ultramine.permission.internal.MetaResolver; +import org.ultramine.permission.internal.PermissionResolver; + import java.util.ArrayList; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Set; public class PermissionRepository { - private Set registeredPermissions; private Map proxyPermissions; public PermissionRepository() { - registeredPermissions = new HashSet(); proxyPermissions = new HashMap(); } public PermissionRepository(PermissionRepository anotherRepository) { - registeredPermissions = new HashSet(anotherRepository.registeredPermissions); proxyPermissions = new HashMap(anotherRepository.proxyPermissions); } @@ -28,72 +27,65 @@ { key = key.toLowerCase(); - if (!proxyPermissions.containsKey(key)) + ProxyPermission permission = proxyPermissions.get(key); + if (permission == null) { if (key.startsWith("^")) - { - proxyPermissions.put(key, new NegativePermission(getPermission(key.substring(1)))); - registeredPermissions.add(key); - } + permission = new NegativePermission(key, getPermission(key.substring(1))); + + else if (key.endsWith(".*") || key.equals("*")) + permission = new ProxyPermission(new DummyPermission(key)); + else - proxyPermissions.put(key, new ProxyPermission(key)); + permission = new ProxyPermission(key); + + proxyPermissions.put(key, permission); } - return proxyPermissions.get(key); + return permission; } public ProxyPermission registerPermission(IPermission permission) { - if (registeredPermissions.contains(permission.getKey())) + ProxyPermission proxy = getPermission(permission.getKey()); + if (!proxy.isDummy()) throw new IllegalArgumentException("Permission already registered"); - if (permission.getKey().startsWith("^")) - throw new IllegalArgumentException("^* names are reserved"); - if (permission instanceof ProxyPermission) { proxyPermissions.put(permission.getKey(), (ProxyPermission)permission); return (ProxyPermission)permission; } - - ProxyPermission proxy = getPermission(permission.getKey()); - if (permission instanceof IChangeablePermission) - proxy.linkChangeable((IChangeablePermission)permission); else - proxy.linkSimple(permission); - - registeredPermissions.add(permission.getKey()); - return proxy; + { + proxy.link(permission); + return proxy; + } } - public static class ProxyPermission implements IChangeablePermission + public static class ProxyPermission implements IPermission { - private String key; private IPermission wrappedPermission; - private ProxyType proxyType; - private List listeners = new ArrayList(); + private boolean isDummy; + private List listeners; public ProxyPermission(String key) { - this.key = key; - this.wrappedPermission = new Permission(key); - this.proxyType = ProxyType.DUMMY; + this.wrappedPermission = new DummyPermission(key); + this.isDummy = true; + listeners = new ArrayList(); } public ProxyPermission(IPermission permission) { - this.key = permission.getKey(); this.wrappedPermission = permission; - if (permission instanceof IChangeablePermission) - proxyType = ProxyType.CHANGEABLE; - else - proxyType = ProxyType.SIMPLE; + this.isDummy = false; } @Override public String getKey() { - return key; + return wrappedPermission.getKey(); } public IPermission getWrappedPermission() @@ -101,79 +93,54 @@ return wrappedPermission; } - public ProxyType getType() + public boolean isDummy() { - return proxyType; + return isDummy; } @Override - public String getName() + public CheckResult check(String key) { - return wrappedPermission.getName(); + return wrappedPermission.check(key); } @Override - public String getDescription() + public String getMeta(String key) { - return wrappedPermission.getDescription(); + return wrappedPermission.getMeta(key); } @Override - public int getPriority() + public void mergePermissionsTo(PermissionResolver resolver) { - return wrappedPermission.getPriority(); + wrappedPermission.mergePermissionsTo(resolver); } @Override - public PermissionResolver getPermissions() + public void mergeMetaTo(MetaResolver resolver) { - return wrappedPermission.getPermissions(); - } - - @Override - public MetaResolver getMeta() - { - return wrappedPermission.getMeta(); + wrappedPermission.mergeMetaTo(resolver); } @Override public void subscribe(IDirtyListener listener) { - switch (proxyType) - { - case CHANGEABLE: - ((IChangeablePermission)wrappedPermission).subscribe(listener); - break; - case DUMMY: - listeners.add(listener); - break; - } + if (isDummy) + listeners.add(listener); + else + wrappedPermission.subscribe(listener); } @Override public void unsubscribe(IDirtyListener listener) { - switch (proxyType) - { - case CHANGEABLE: - ((IChangeablePermission)wrappedPermission).unsubscribe(listener); - break; - case DUMMY: - listeners.remove(listener); - break; - } + if (isDummy) + listeners.remove(listener); + else + wrappedPermission.unsubscribe(listener); } - private void linkSimple(IPermission permission) - { - wrappedPermission = permission; - for (IDirtyListener listener : listeners) - listener.makeDirty(); - listeners.clear(); - proxyType = ProxyType.SIMPLE; - } - - private void linkChangeable(IChangeablePermission permission) + private void link(IPermission permission) { wrappedPermission = permission; for (IDirtyListener listener : listeners) @@ -181,8 +148,8 @@ permission.subscribe(listener); listener.makeDirty(); } - listeners.clear(); - proxyType = ProxyType.CHANGEABLE; + listeners = null; + isDummy = false; } @Override @@ -202,7 +169,5 @@ { return wrappedPermission.toString(); } - - public static enum ProxyType { DUMMY, SIMPLE, CHANGEABLE } } -} +} \ No newline at end of file diff --git a/src/main/java/org/ultramine/permission/PermissionResolver.java b/src/main/java/org/ultramine/permission/PermissionResolver.java deleted file mode 100644 index 7c7ba4f..0000000 --- a/src/main/java/org/ultramine/permission/PermissionResolver.java +++ /dev/null @@ -1,56 +0,0 @@ -package org.ultramine.permission; - -import java.util.Map; - -public class PermissionResolver extends Resolver -{ - public static PermissionResolver createInverted(PermissionResolver anotherResolver) - { - PermissionResolver resolver = new PermissionResolver(); - for (Map.Entry entry : anotherResolver.values.entrySet()) - { - resolver.values.put(entry.getKey(), !entry.getValue()); - resolver.priorities.put(entry.getKey(), anotherResolver.priorities.get(entry.getKey())); - } - return resolver; - } - - public static PermissionResolver createForKey(String key, int priority) - { - PermissionResolver resolver = new PermissionResolver(); - resolver.values.put(key, true); - resolver.priorities.put(key, priority); - return resolver; - } - - public CheckResult check(String key) - { - if (key == null) - return CheckResult.UNRESOLVED; - - key = key.toLowerCase(); - if (values.containsKey(key)) - return toCheckResult(values.get(key)); - - int index = key.lastIndexOf('.'); - while (index >= 0) - { - key = key.substring(0, index); - String wildcard = key + ".*"; - if (values.containsKey(wildcard)) - return toCheckResult(values.get(wildcard)); - - index = key.lastIndexOf('.'); - } - if (values.containsKey("*")) - return toCheckResult(values.get("*")); - - return CheckResult.UNRESOLVED; - } - - public enum CheckResult { TRUE, FALSE, UNRESOLVED } - private CheckResult toCheckResult(boolean bool) - { - return bool ? CheckResult.TRUE : CheckResult.FALSE; - } -} diff --git a/src/main/java/org/ultramine/permission/Resolver.java b/src/main/java/org/ultramine/permission/Resolver.java deleted file mode 100644 index 48b3b21..0000000 --- a/src/main/java/org/ultramine/permission/Resolver.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.ultramine.permission; - -import gnu.trove.map.hash.TObjectIntHashMap; - -import java.util.HashMap; -import java.util.Map; - -public class Resolver -{ - protected Map values = new HashMap(); - protected TObjectIntHashMap priorities = new TObjectIntHashMap(); - - public void clear() - { - values.clear(); - priorities.clear(); - } - - public void merge(Resolver anotherResolver, int priority) - { - merge(anotherResolver.values, priority); - } - - public void merge(Map newValues, int priority) - { - for (String key : newValues.keySet()) - if (!priorities.containsKey(key) || priorities.get(key) < priority) - { - values.put(key, newValues.get(key)); - priorities.put(key, priority); - } - } -} diff --git a/src/main/java/org/ultramine/permission/ServerPermissionManager.java b/src/main/java/org/ultramine/permission/ServerPermissionManager.java deleted file mode 100644 index a4d7f1a..0000000 --- a/src/main/java/org/ultramine/permission/ServerPermissionManager.java +++ /dev/null @@ -1,231 +0,0 @@ -package org.ultramine.permission; - -import org.ultramine.server.util.YamlConfigProvider; - -import java.io.File; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -public class ServerPermissionManager implements IPermissionHandler -{ - private final static String GLOBAL_WORLD = "global"; - private final static String GROUPS_CONFIG = "groups.yml"; - - private File configDir; - private Map worlds; - private PermissionRepository permissionRepository; - private Map groups; - - public ServerPermissionManager(File configDir, PermissionRepository permissionRepository) - { - this.configDir = new File(configDir, "permissions"); - if (!this.configDir.exists()) - this.configDir.mkdir(); - - this.permissionRepository = permissionRepository; - this.worlds = new HashMap(); - this.groups = new HashMap(); - reloadGroups(); - reloadWorld(GLOBAL_WORLD); - } - - - @Override - public boolean has(String world, String player, String permission) - { - if (!worlds.containsKey(world)) - return getGlobal().checkUserPermission(player, permission); - - return getWorld(world).checkUserPermission(player, permission); - } - - @Override - public void add(String world, String player, String permission) - { - if (!worlds.containsKey(world)) - reloadWorld(world); - - World worldContainer = getWorld(world); - if (!worldContainer.contains(player)) - worldContainer.add(new User(player)); - - worldContainer.get(player).addPermission(permissionRepository.getPermission(permission)); - } - - @Override - public void add(String world, String permission) - { - if (!worlds.containsKey(world)) - reloadWorld(world); - - getWorld(world).getDefaultPermissions().addPermission(permissionRepository.getPermission(permission)); - } - - @Override - public void remove(String world, String player, String permission) - { - if (!worlds.containsKey(world)) - return; - - World worldContainer = getWorld(world); - if (!worldContainer.contains(player)) - return; - - worldContainer.get(player).removePermission(permission); - } - - @Override - public void remove(String world, String permission) - { - if (!worlds.containsKey(world)) - return; - - getWorld(world).getDefaultPermissions().removePermission(permission); - } - - @Override - public MetaResolver getMeta(String world, String player) - { - if (!worlds.containsKey(world)) - return MetaResolver.BLANK_RESOLVER; - - World worldContainer = getWorld(world); - if (!worldContainer.contains(player)) - return MetaResolver.BLANK_RESOLVER; - - return worldContainer.get(player).getMeta(); - } - - @Override - public void setMeta(String world, String player, String key, Object value) - { - if (!worlds.containsKey(world)) - reloadWorld(world); - - World worldContainer = getWorld(world); - if (!worldContainer.contains(player)) - worldContainer.add(new User(player)); - - worldContainer.get(player).setMeta(key, value); - } - - @Override - public Set findUsersWithPermission(String world, String permission) - { - if (!worlds.containsKey(world)) - return getGlobal().getAllWithPermission(permission); - - return getWorld(world).getAllWithPermission(permission); - } - - @Override - public void save() - { - saveGroups(); - for (String world : worlds.keySet()) - saveWorld(world); - } - - @Override - public void reload() - { - reloadGroups(); - for (String world : worlds.keySet()) - reloadWorld(world); - } - - @Override - public PermissionRepository getRepository() - { - return permissionRepository; - } - - public void reloadWorld(String name) - { - World.WorldData data = YamlConfigProvider.getOrCreateConfig(worldFile(name), World.WorldData.class); - if (!worlds.containsKey(name)) - worlds.put(name, new World(permissionRepository)); - - worlds.get(name).load(data); - - if (!name.equals(GLOBAL_WORLD)) - worlds.get(name).setParentContainer(getGlobal()); - - } - - public void saveWorld(String name) - { - if (!worlds.containsKey(name)) - return; - - YamlConfigProvider.saveConfig(worldFile(name), worlds.get(name).save()); - } - - public void reloadGroups() - { - for (GroupPermission group : groups.values()) - { - group.clearPermissions(); - group.clearMeta(); - } - - GroupData data = YamlConfigProvider.getOrCreateConfig(groupsFile(), GroupData.class); - if (data == null || data.groups == null) - return; - - for (Map.Entry groupData : data.groups.entrySet()) - { - GroupPermission group; - if (!groups.containsKey(groupData.getKey())) - { - group = new GroupPermission(groupData.getKey(), groupData.getValue().meta); - permissionRepository.registerPermission(group); - groups.put(groupData.getKey(), group); - } - else - { - group = groups.get(groupData.getKey()); - group.setInnerMeta(groupData.getValue().meta); - } - - for (String pKey : groupData.getValue().permissions) - group.addPermission(permissionRepository.getPermission(pKey)); - } - } - - public void saveGroups() - { - GroupData data = new GroupData(); - - for (Map.Entry group : groups.entrySet()) - data.groups.put(group.getKey(), new World.HolderData(group.getValue())); - - YamlConfigProvider.saveConfig(groupsFile(), data); - } - - public World getWorld(String name) - { - return worlds.get(name); - } - - public World getGlobal() - { - return getWorld(GLOBAL_WORLD); - } - - private File worldFile(String name) - { - return new File(configDir, "users-" + name + ".yml"); - } - - private File groupsFile() - { - return new File(configDir, GROUPS_CONFIG); - } - - public static class GroupData - { - public Map groups = new HashMap(); - } -} diff --git a/src/main/java/org/ultramine/permission/User.java b/src/main/java/org/ultramine/permission/User.java index 78f77ec..80c9f4b 100644 --- a/src/main/java/org/ultramine/permission/User.java +++ b/src/main/java/org/ultramine/permission/User.java @@ -1,5 +1,7 @@ package org.ultramine.permission; +import org.ultramine.permission.internal.PermissionHolder; + import java.util.Map; public class User extends PermissionHolder @@ -12,7 +14,7 @@ this.name = name.toLowerCase(); } - public User(String name, Map meta) + public User(String name, Map meta) { super(meta); this.name = name.toLowerCase(); @@ -22,10 +24,4 @@ { return name; } - - @Override - public int getPriority() - { - return getMeta().getInt("priority"); - } } \ No newline at end of file diff --git a/src/main/java/org/ultramine/permission/UserContainer.java b/src/main/java/org/ultramine/permission/UserContainer.java deleted file mode 100644 index e47bfbe..0000000 --- a/src/main/java/org/ultramine/permission/UserContainer.java +++ /dev/null @@ -1,99 +0,0 @@ -package org.ultramine.permission; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -import static org.ultramine.permission.PermissionResolver.CheckResult; - -public class UserContainer -{ - protected Map users; - protected UserContainer parentContainer; - - public UserContainer() - { - users = new HashMap(); - } - - public UserContainer(UserContainer parentContainer) - { - this(); - this.parentContainer = parentContainer; - } - - public final boolean checkUserPermission(String userName, String permissionKey) - { - return check(userName, permissionKey) == CheckResult.TRUE; - } - - protected CheckResult check(String userName, String permissionKey) - { - userName = userName.toLowerCase(); - CheckResult result = CheckResult.UNRESOLVED; - - if (parentContainer != null) - result = parentContainer.check(userName, permissionKey); - - if (result == CheckResult.UNRESOLVED && contains(userName)) - result = get(userName).getPermissions().check(permissionKey); - - return result; - } - - public T get(String name) - { - return users.get(name.toLowerCase()); - } - - public Set getAllWithPermission(String permission) - { - Set result; - if (parentContainer != null) - result = parentContainer.getAllWithPermission(permission); - else - result = new HashSet(); - - for (User user : users.values()) - { - if (user.getPermissions().check(permission) == CheckResult.TRUE) - result.add(user.getName()); - } - - return result; - } - - public void add(T user) - { - if (users.containsKey(user.getName())) - return; - - users.put(user.getName(), user); - } - - public void remove(String name) - { - users.remove(name.toLowerCase()); - } - - public void remove(User user) - { - remove(user.getName()); - } - - public void clear() - { - users.clear(); - } - - public boolean contains(String name) - { - return users.containsKey(name); - } - - public boolean contains(User user) - { - return contains(user.getName()); - } -} diff --git a/src/main/java/org/ultramine/permission/World.java b/src/main/java/org/ultramine/permission/World.java index db24b0f..21b30d0 100644 --- a/src/main/java/org/ultramine/permission/World.java +++ b/src/main/java/org/ultramine/permission/World.java @@ -1,5 +1,9 @@ package org.ultramine.permission; +import org.ultramine.permission.internal.CheckResult; +import org.ultramine.permission.internal.PermissionHolder; +import org.ultramine.permission.internal.UserContainer; + import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -7,16 +11,14 @@ public class World extends UserContainer { - private PermissionRepository repository; private GroupPermission defaultPermissions; - public World(PermissionRepository permissionRepository) + public World() { - this.repository = permissionRepository; this.defaultPermissions = new GroupPermission(""); } - public void load(WorldData data) + public void load(PermissionRepository repository, WorldData data) { if (data == null) return; @@ -65,12 +67,12 @@ } @Override - protected PermissionResolver.CheckResult check(String userName, String permissionKey) + protected CheckResult check(String userName, String permissionKey) { - PermissionResolver.CheckResult result = super.check(userName, permissionKey); + CheckResult result = super.check(userName, permissionKey); - if (result == PermissionResolver.CheckResult.UNRESOLVED) - result = defaultPermissions.getPermissions().check(permissionKey); + if (result == CheckResult.UNRESOLVED) + result = defaultPermissions.check(permissionKey); return result; } @@ -84,12 +86,12 @@ public static class HolderData { public List permissions; - public Map meta; + public Map meta; public HolderData() { permissions = new ArrayList(); - meta = new HashMap(); + meta = new HashMap(); } public HolderData(PermissionHolder holder) diff --git a/src/main/java/org/ultramine/permission/commands/BasicPermissionCommands.java b/src/main/java/org/ultramine/permission/commands/BasicPermissionCommands.java new file mode 100644 index 0000000..304b49f --- /dev/null +++ b/src/main/java/org/ultramine/permission/commands/BasicPermissionCommands.java @@ -0,0 +1,188 @@ +package org.ultramine.permission.commands; + +import net.minecraft.command.WrongUsageException; +import org.ultramine.commands.Action; +import org.ultramine.commands.Command; +import org.ultramine.commands.CommandContext; +import org.ultramine.server.PermissionHandler; + +public class BasicPermissionCommands +{ + @Command( + name = "pconfig", + group = "permissions", + aliases = {"permissions", "pcfg"}, + permissions = {"permissions.admin"}, + syntax = {"[save reload]"} + ) + public static void pcofnig(CommandContext context) + { + if (context.getAction().equals("save")) + { + PermissionHandler.getInstance().save(); + context.notifyAdmins("command.pconfig.success.save"); + } + else if (context.getAction().equals("reload")) + { + PermissionHandler.getInstance().reload(); + context.notifyAdmins("command.pconfig.success.reload"); + } + } + + + + @Command( + name = "pworld", + group = "permissions", + permissions = {"permissions.admin.world"}, + syntax = { + "[add remove] ...", + " [add remove] ..." + } + ) + public static void pworld(CommandContext context) + { + if (!context.contains("world")) + { + if (context.senderIsServer()) + throw new WrongUsageException("command.permissions.serverworld"); + + context.set("world", context.getSenderAsPlayer().getEntityWorld().getWorldInfo().getWorldName()); + } + + context.checkSenderPermissionInWorld(context.get("world").asString(), "permissions.admin.world"); + context.doAction(); + } + + @Action(command = "pworld", name = "add") + public static void pworld_add(CommandContext context) + { + String world = context.get("world").asString(); + + for (CommandContext.Argument arg : context.get("permission").asArray()) + { + PermissionHandler.getInstance().addToWorld(world, arg.asString()); + context.notifyAdmins("command.pworld.success.add", arg.asString(), world); + } + } + + @Action(command = "pworld", name = "remove") + public static void pworld_remove(CommandContext context) + { + String world = context.get("world").asString(); + + for (CommandContext.Argument arg : context.get("permission").asArray()) + { + PermissionHandler.getInstance().removeFromWorld(world, arg.asString()); + context.notifyAdmins("command.pworld.success.remove", arg.asString(), world); + } + } + + + + @Command( + name = "puser", + group = "permissions", + permissions = {"permissions.admin.user"}, + syntax = { + " [add remove] ...", + " [meta] <%value>", + " [add remove] ...", + " [meta] <%value>" + } + ) + public static void puser(CommandContext context) + { + if (!context.contains("world")) + { + if (context.senderIsServer()) + throw new WrongUsageException("command.permissions.serverworld"); + + context.set("world", context.getSenderAsPlayer().getEntityWorld().getWorldInfo().getWorldName()); + } + + context.checkSenderPermissionInWorld(context.get("world").asString(), "permissions.admin.user"); + context.doAction(); + } + + @Action(command = "puser", name = "add") + public static void puser_add(CommandContext context) + { + String world = context.get("world").asString(); + String player = context.get("player").asString(); + + for (CommandContext.Argument arg : context.get("permission").asArray()) + { + PermissionHandler.getInstance().add(world, player, arg.asString()); + context.notifyAdmins("command.puser.success.add", arg.asString(), player, world); + } + } + + @Action(command = "puser", name = "remove") + public static void puser_remove(CommandContext context) + { + String world = context.get("world").asString(); + String player = context.get("player").asString(); + + for (CommandContext.Argument arg : context.get("permission").asArray()) + { + PermissionHandler.getInstance().remove(world, player, arg.asString()); + context.notifyAdmins("command.puser.success.remove", arg.asString(), player, world); + } + } + + @Action(command = "puser", name = "meta") + public static void puser_meta(CommandContext context) + { + String world = context.get("world").asString(); + String player = context.get("player").asString(); + String key = context.get("pmeta").asString(); + String value = context.get("value").asString(); + + PermissionHandler.getInstance().setMeta(world, player, key, value); + context.notifyAdmins("command.puser.success.meta", key, value, player, world); + } + + + + @Command( + name = "pgroup", + group = "permissions", + permissions = {"permissions.admin.group"}, + syntax = { + " [add remove] ...", + " [meta] <%value>" + } + ) + public static void pgroup(CommandContext context) + { + String group = context.get("group").asString(); + + if (context.getAction().equals("add")) + { + for (CommandContext.Argument arg : context.get("permission").asArray()) + { + PermissionHandler.getInstance().addToGroup(group, arg.asString()); + context.notifyAdmins("command.pgroup.success.add", arg.asString(), group); + } + } + + else if (context.getAction().equals("remove")) + { + for (CommandContext.Argument arg : context.get("permission").asArray()) + { + PermissionHandler.getInstance().removeFromGroup(group, arg.asString()); + context.notifyAdmins("command.pgroup.success.remove", arg.asString(), group); + } + } + + else if (context.getAction().equals("meta")) + { + String key = context.get("key").asString(); + String value = context.get("value").asString(); + PermissionHandler.getInstance().setGroupMeta(group, key, value); + context.notifyAdmins("command.pgroup.success.meta", key, value, group); + } + } + +} diff --git a/src/main/java/org/ultramine/permission/internal/CheckResult.java b/src/main/java/org/ultramine/permission/internal/CheckResult.java new file mode 100644 index 0000000..eca8663 --- /dev/null +++ b/src/main/java/org/ultramine/permission/internal/CheckResult.java @@ -0,0 +1,29 @@ +package org.ultramine.permission.internal; + +public enum CheckResult +{ + TRUE, FALSE, UNRESOLVED; + + public static CheckResult fromBoolean(boolean value) + { + return value ? TRUE : FALSE; + } + + public boolean asBoolean() + { + return this == TRUE; + } + + public CheckResult invert() + { + switch (this) + { + case TRUE: + return FALSE; + case FALSE: + return TRUE; + default: + return UNRESOLVED; + } + } +} \ No newline at end of file diff --git a/src/main/java/org/ultramine/permission/internal/ClientPermissionManager.java b/src/main/java/org/ultramine/permission/internal/ClientPermissionManager.java new file mode 100644 index 0000000..74c3980 --- /dev/null +++ b/src/main/java/org/ultramine/permission/internal/ClientPermissionManager.java @@ -0,0 +1,146 @@ +package org.ultramine.permission.internal; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import org.ultramine.permission.GroupPermission; +import org.ultramine.permission.IPermissionManager; +import org.ultramine.permission.PermissionRepository; +import org.ultramine.permission.User; +import org.ultramine.permission.World; + +import java.util.HashMap; +import java.util.Map; + +@SideOnly(Side.CLIENT) +public class ClientPermissionManager implements IPermissionManager +{ + private World global; + private PermissionRepository permissionRepository; + private Map groups; + private String owner; + + public ClientPermissionManager(String owner, PermissionRepository permissionRepository) + { + this.permissionRepository = permissionRepository; + this.global = new World(); + this.groups = new HashMap(); + this.owner = owner; + } + + @Override + public boolean has(String world, String player, String permission) + { + return player.equalsIgnoreCase(owner) || global.checkUserPermission(player, permission); + } + + @Override + public void add(String world, String player, String permission) + { + getOrCreateUser(player).addPermission(permissionRepository.getPermission(permission)); + } + + @Override + public void addToWorld(String world, String permission) + { + global.getDefaultPermissions().addPermission(permissionRepository.getPermission(permission)); + } + + @Override + public void addToGroup(String group, String permission) + { + getOrCreateGroup(group).addPermission(permissionRepository.getPermission(permission)); + } + + @Override + public void remove(String world, String player, String permission) + { + User user = global.get(player); + if (user == null) + return; + + user.removePermission(permission); + } + + @Override + public void removeFromWorld(String world, String permission) + { + global.getDefaultPermissions().removePermission(permission); + } + + @Override + public void removeFromGroup(String group, String permission) + { + GroupPermission groupObj = groups.get(ServerPermissionManager.fixGroupKey(group)); + groupObj.removePermission(permission); + } + + @Override + public String getMeta(String world, String player, String key) + { + User user = global.get(player); + if (user == null) + return ""; + else + return user.getMeta(key); + } + + @Override + public void setMeta(String world, String player, String key, String value) + { + getOrCreateUser(player).setMeta(key, value); + } + + @Override + public void setGroupMeta(String group, String key, String value) + { + getOrCreateGroup(group).setMeta(key, value); + } + + @Override + public void save() + { + } + + @Override + public void reload() + { + } + + @Override + public PermissionRepository getRepository() + { + return permissionRepository; + } + + @Override + public UserContainer getWorldContainer(String world) + { + return global; + } + + private User getOrCreateUser(String name) + { + User user = global.get(name); + if (user == null) + { + user = new User(name); + global.add(user); + } + + return user; + } + + private GroupPermission getOrCreateGroup(String name) + { + String groupKey = ServerPermissionManager.fixGroupKey(name); + GroupPermission group = groups.get(groupKey); + if (group == null) + { + group = new GroupPermission(groupKey); + permissionRepository.registerPermission(group); + groups.put(groupKey, group); + } + + return group; + } +} diff --git a/src/main/java/org/ultramine/permission/internal/MetaHolder.java b/src/main/java/org/ultramine/permission/internal/MetaHolder.java new file mode 100644 index 0000000..7c2dc6d --- /dev/null +++ b/src/main/java/org/ultramine/permission/internal/MetaHolder.java @@ -0,0 +1,56 @@ +package org.ultramine.permission.internal; + +import java.util.HashMap; +import java.util.Map; + +public abstract class MetaHolder +{ + private Map innerMeta; + + public MetaHolder() + { + innerMeta = new HashMap(); + } + + public MetaHolder(Map meta) + { + setInnerMeta(meta); + } + + public String getMeta(String key) + { + return getMetaResolver().getString(key); + } + + public void setMeta(String key, String value) + { + innerMeta.put(key, value); + } + + public void removeMeta(String key) + { + innerMeta.remove(key); + } + + public void clearMeta() + { + innerMeta.clear(); + } + + public Map getInnerMeta() + { + return new HashMap(innerMeta); + } + + public void setInnerMeta(Map meta) + { + innerMeta = new HashMap(meta); + } + + protected abstract MetaResolver getMetaResolver(); + + protected void mergeInnerMeta() + { + getMetaResolver().merge(innerMeta, Integer.MAX_VALUE); + } +} diff --git a/src/main/java/org/ultramine/permission/internal/MetaResolver.java b/src/main/java/org/ultramine/permission/internal/MetaResolver.java new file mode 100644 index 0000000..76baea7 --- /dev/null +++ b/src/main/java/org/ultramine/permission/internal/MetaResolver.java @@ -0,0 +1,35 @@ +package org.ultramine.permission.internal; + +public class MetaResolver extends Resolver +{ + public static final MetaResolver BLANK_RESOLVER = new MetaResolver(); + + public MetaResolver() + { + super(); + } + + public String getString(String key) + { + if (values.containsKey(key)) + return values.get(key); + else + return ""; + } + + public int getInt(String key) + { + if (values.containsKey(key)) + { + try + { + return Integer.parseInt(values.get(key)); + } + catch (Exception ignored) + { + } + } + + return 0; + } +} diff --git a/src/main/java/org/ultramine/permission/internal/PermissionHolder.java b/src/main/java/org/ultramine/permission/internal/PermissionHolder.java new file mode 100644 index 0000000..2bf7aae --- /dev/null +++ b/src/main/java/org/ultramine/permission/internal/PermissionHolder.java @@ -0,0 +1,143 @@ +package org.ultramine.permission.internal; + +import org.ultramine.permission.IDirtyListener; +import org.ultramine.permission.IPermission; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class PermissionHolder extends MetaHolder implements IDirtyListener +{ + private boolean dirty; + + private Map permissions = new HashMap(); + private PermissionResolver permissionResolver = new PermissionResolver(); + private MetaResolver metaResolver = new MetaResolver(); + + public PermissionHolder() + { + super(); + this.dirty = false; + } + + public PermissionHolder(Map meta) + { + super(meta); + this.dirty = true; + } + + public CheckResult check(String key) + { + return getPermissionResolver().check(key); + } + + public void addPermission(IPermission permission) + { + if (permissions.containsKey(permission.getKey())) + return; + + permissions.put(permission.getKey(), permission); + permission.subscribe(this); + + makeDirty(); + } + + public void removePermission(IPermission permission) + { + removePermission(permission.getKey()); + } + + public void removePermission(String key) + { + if (!permissions.containsKey(key)) + return; + + IPermission permission = permissions.remove(key); + permission.unsubscribe(this); + + makeDirty(); + } + + public void clearPermissions() + { + for (IPermission permission : permissions.values()) + permission.unsubscribe(this); + + permissions.clear(); + makeDirty(); + } + + public List getInnerPermissions() + { + return new ArrayList(permissions.keySet()); + } + + public boolean isDirty() + { + return dirty; + } + + @Override + public void makeDirty() + { + dirty = true; + } + + @Override + public void setMeta(String key, String value) + { + super.setMeta(key, value); + makeDirty(); + } + + @Override + public void removeMeta(String key) + { + super.removeMeta(key); + makeDirty(); + } + + @Override + public void clearMeta() + { + super.clearMeta(); + makeDirty(); + } + + public void calculate() + { + if (!isDirty()) + return; + dirty = false; + + permissionResolver.clear(); + metaResolver.clear(); + + for (IPermission permission : permissions.values()) + { + permission.mergePermissionsTo(permissionResolver); + permission.mergeMetaTo(metaResolver); + } + + mergeInnerMeta(); + } + + protected PermissionResolver getPermissionResolver() + { + if (isDirty()) + calculate(); + + return permissionResolver; + } + + @Override + protected MetaResolver getMetaResolver() + { + if (isDirty()) + calculate(); + + return metaResolver; + } +} \ No newline at end of file diff --git a/src/main/java/org/ultramine/permission/internal/PermissionResolver.java b/src/main/java/org/ultramine/permission/internal/PermissionResolver.java new file mode 100644 index 0000000..33465ed --- /dev/null +++ b/src/main/java/org/ultramine/permission/internal/PermissionResolver.java @@ -0,0 +1,68 @@ +package org.ultramine.permission.internal; + +import java.util.*; + +public class PermissionResolver extends Resolver +{ + private SortedMap wildcards; + + public PermissionResolver() + { + super(); + this.wildcards = new TreeMap(Collections.reverseOrder()); + } + + public static PermissionResolver createInverted(PermissionResolver anotherResolver) + { + PermissionResolver resolver = new PermissionResolver(); + for (Map.Entry entry : anotherResolver.values.entrySet()) + resolver.merge(entry.getKey(), !entry.getValue(), anotherResolver.priorities.get(entry.getKey())); + + return resolver; + } + + public static PermissionResolver createForKey(String key, int priority) + { + PermissionResolver resolver = new PermissionResolver(); + resolver.merge(key, true, priority); + return resolver; + } + + public CheckResult check(String key) + { + if (key == null) + return CheckResult.UNRESOLVED; + + key = key.toLowerCase(); + if (values.containsKey(key)) + return CheckResult.fromBoolean(values.get(key)); + + if (wildcards.size() > 0) + { + for (Map.Entry entry : wildcards.entrySet()) + { + if (key.startsWith(entry.getKey())) + return CheckResult.fromBoolean(entry.getValue()); + } + } + + return CheckResult.UNRESOLVED; + } + + @Override + public void clear() + { + super.clear(); + wildcards.clear(); + } + + @Override + public boolean merge(String key, Boolean value, int priority) + { + boolean result = super.merge(key, value, priority); + if (result && (key.endsWith(".*") || key.equals("*"))) + wildcards.put(key.substring(0, key.length() - 1), value); + + return result; + } +} \ No newline at end of file diff --git a/src/main/java/org/ultramine/permission/internal/Resolver.java b/src/main/java/org/ultramine/permission/internal/Resolver.java new file mode 100644 index 0000000..1966f64 --- /dev/null +++ b/src/main/java/org/ultramine/permission/internal/Resolver.java @@ -0,0 +1,48 @@ +package org.ultramine.permission.internal; + +import gnu.trove.map.hash.TObjectIntHashMap; + +import java.util.HashMap; +import java.util.Map; + +public class Resolver +{ + protected Map values; + protected TObjectIntHashMap priorities; + + public Resolver() + { + values = new HashMap(); + priorities = new TObjectIntHashMap(); + } + + public void clear() + { + values.clear(); + priorities.clear(); + } + + public final void merge(Resolver anotherResolver, int priority) + { + if (anotherResolver != null) + merge(anotherResolver.values, priority); + } + + public final void merge(Map newValues, int priority) + { + for (Map.Entry entry : newValues.entrySet()) + merge(entry.getKey(), entry.getValue(), priority); + + } + + public boolean merge(String key, T value, int priority) + { + if (!priorities.containsKey(key) || priorities.get(key) < priority) + { + values.put(key, value); + priorities.put(key, priority); + return true; + } + return false; + } +} diff --git a/src/main/java/org/ultramine/permission/internal/ServerPermissionManager.java b/src/main/java/org/ultramine/permission/internal/ServerPermissionManager.java new file mode 100644 index 0000000..2f1c8b8 --- /dev/null +++ b/src/main/java/org/ultramine/permission/internal/ServerPermissionManager.java @@ -0,0 +1,277 @@ +package org.ultramine.permission.internal; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import org.ultramine.permission.GroupPermission; +import org.ultramine.permission.IPermissionManager; +import org.ultramine.permission.PermissionRepository; +import org.ultramine.permission.User; +import org.ultramine.permission.World; +import org.ultramine.server.util.YamlConfigProvider; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; + +@SideOnly(Side.SERVER) +public class ServerPermissionManager implements IPermissionManager +{ + public final static String GLOBAL_WORLD = "global"; + private final static String GROUPS_CONFIG = "groups.yml"; + private static final String GROUP_PREFIX = "group."; + + private File configDir; + private Map worlds; + private PermissionRepository permissionRepository; + private Map groups; + + public ServerPermissionManager(File configDir, PermissionRepository permissionRepository) + { + this.configDir = new File(configDir, "permissions"); + if (!this.configDir.exists()) + this.configDir.mkdir(); + + this.permissionRepository = permissionRepository; + this.worlds = new HashMap(); + this.groups = new HashMap(); + reloadGroups(); + reloadWorld(GLOBAL_WORLD); + } + + @Override + public PermissionRepository getRepository() + { + return permissionRepository; + } + + @Override + public UserContainer getWorldContainer(String world) + { + return worlds.get(world); + } + + @Override + public boolean has(String world, String player, String permission) + { + World worldObj = worlds.get(world); + if (worldObj == null) + worldObj = worlds.get(GLOBAL_WORLD); + + return worldObj.checkUserPermission(player, permission); + } + + @Override + public void add(String world, String player, String permission) + { + getOrCreateUser(world, player).addPermission(permissionRepository.getPermission(permission)); + } + + @Override + public void addToWorld(String world, String permission) + { + getOrCreateWorld(world).getDefaultPermissions() + .addPermission(permissionRepository.getPermission(permission)); + } + + @Override + public void addToGroup(String group, String permission) + { + getOrCreateGroup(group).addPermission(permissionRepository.getPermission(permission)); + } + + @Override + public void remove(String world, String player, String permission) + { + User user = getUser(world, player); + if (user == null) + return; + + user.removePermission(permission); + } + + @Override + public void removeFromWorld(String world, String permission) + { + World worldObj = worlds.get(world); + if (worldObj == null) + return; + + worldObj.getDefaultPermissions().removePermission(permission); + } + + @Override + public void removeFromGroup(String group, String permission) + { + GroupPermission groupObj = groups.get(fixGroupKey(group)); + if (groupObj == null) + return; + + groupObj.removePermission(permission); + } + + @Override + public String getMeta(String world, String player, String key) + { + User user = getUser(world, player); + if (user == null) + return ""; + else + return user.getMeta(key); + } + + @Override + public void setMeta(String world, String player, String key, String value) + { + getOrCreateUser(world, player).setMeta(key, value); + } + + @Override + public void setGroupMeta(String group, String key, String value) + { + getOrCreateGroup(group).setMeta(key, value); + } + + @Override + public void save() + { + saveGroups(); + for (String world : worlds.keySet()) + saveWorld(world); + } + + @Override + public void reload() + { + reloadGroups(); + for (String world : worlds.keySet()) + reloadWorld(world); + } + + public World reloadWorld(String name) + { + World.WorldData data = YamlConfigProvider.getOrCreateConfig(worldFile(name), World.WorldData.class); + World world = worlds.get(name); + if (world == null) + { + world = new World(); + worlds.put(name, world); + } + + world.load(permissionRepository, data); + + if (!name.equals(GLOBAL_WORLD)) + world.setParentContainer(worlds.get(GLOBAL_WORLD)); + + return world; + } + + public void saveWorld(String name) + { + World world = worlds.get(name); + if (world == null) + return; + + YamlConfigProvider.saveConfig(worldFile(name), world.save()); + } + + public void reloadGroups() + { + for (GroupPermission group : groups.values()) + { + group.clearPermissions(); + group.clearMeta(); + } + + GroupData data = YamlConfigProvider.getOrCreateConfig(groupsFile(), GroupData.class); + if (data == null || data.groups == null) + return; + + for (Map.Entry groupData : data.groups.entrySet()) + { + GroupPermission group = getOrCreateGroup(groupData.getKey()); + group.setInnerMeta(groupData.getValue().meta); + + for (String pKey : groupData.getValue().permissions) + group.addPermission(permissionRepository.getPermission(pKey)); + } + } + + public void saveGroups() + { + GroupData data = new GroupData(); + + for (Map.Entry group : groups.entrySet()) + data.groups.put(group.getKey(), new World.HolderData(group.getValue())); + + YamlConfigProvider.saveConfig(groupsFile(), data); + } + + private World getOrCreateWorld(String name) + { + World world = worlds.get(name); + if (world == null) + world = reloadWorld(name); + + return world; + } + + private User getUser(String worldName, String userName) + { + World world = worlds.get(worldName); + if (world == null) + return null; + + return world.get(userName); + } + + private User getOrCreateUser(String worldName, String userName) + { + World world = getOrCreateWorld(worldName); + + User user = world.get(userName); + if (user == null) + { + user = new User(userName); + world.add(user); + } + + return user; + } + + public static String fixGroupKey(String key) + { + if (key.startsWith(GROUP_PREFIX)) + return key; + else + return GROUP_PREFIX + key; + } + + private GroupPermission getOrCreateGroup(String name) + { + String groupKey = fixGroupKey(name); + GroupPermission group = groups.get(groupKey); + if (group == null) + { + group = new GroupPermission(groupKey); + permissionRepository.registerPermission(group); + groups.put(groupKey, group); + } + + return group; + } + + private File worldFile(String name) + { + return new File(configDir, "users-" + name + ".yml"); + } + + private File groupsFile() + { + return new File(configDir, GROUPS_CONFIG); + } + + public static class GroupData + { + public Map groups = new HashMap(); + } +} diff --git a/src/main/java/org/ultramine/permission/internal/UserContainer.java b/src/main/java/org/ultramine/permission/internal/UserContainer.java new file mode 100644 index 0000000..9ed1ca1 --- /dev/null +++ b/src/main/java/org/ultramine/permission/internal/UserContainer.java @@ -0,0 +1,100 @@ +package org.ultramine.permission.internal; + +import org.ultramine.permission.User; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +public class UserContainer +{ + protected Map users; + protected UserContainer parentContainer; + + public UserContainer() + { + users = new HashMap(); + } + + public UserContainer(UserContainer parentContainer) + { + this(); + this.parentContainer = parentContainer; + } + + public final boolean checkUserPermission(String userName, String permissionKey) + { + return check(userName, permissionKey).asBoolean(); + } + + protected CheckResult check(String userName, String permissionKey) + { + userName = userName.toLowerCase(); + CheckResult result = CheckResult.UNRESOLVED; + + if (parentContainer != null) + result = parentContainer.check(userName, permissionKey); + + if (result == CheckResult.UNRESOLVED && contains(userName)) + result = get(userName).check(permissionKey); + + return result; + } + + public T get(String name) + { + return users.get(name.toLowerCase()); + } + + public Set getAllWithPermission(String permission) + { + Set result; + if (parentContainer != null) + result = parentContainer.getAllWithPermission(permission); + else + result = new HashSet(); + + for (String username : users.keySet()) + { + if (!result.contains(username) && checkUserPermission(username, permission)) + result.add(username); + } + + return result; + } + + public void add(T user) + { + if (users.containsKey(user.getName())) + return; + + users.put(user.getName(), user); + } + + public void remove(String name) + { + users.remove(name.toLowerCase()); + } + + public void remove(User user) + { + remove(user.getName()); + } + + public void clear() + { + users.clear(); + parentContainer = null; + } + + public boolean contains(String name) + { + return users.containsKey(name); + } + + public boolean contains(User user) + { + return contains(user.getName()); + } +} diff --git a/src/main/java/org/ultramine/server/PermissionHandler.java b/src/main/java/org/ultramine/server/PermissionHandler.java index b8f05ac..d25037b 100644 --- a/src/main/java/org/ultramine/server/PermissionHandler.java +++ b/src/main/java/org/ultramine/server/PermissionHandler.java @@ -1,85 +1,29 @@ package org.ultramine.server; import net.minecraft.command.ICommandSender; -import org.ultramine.permission.ClientPermissionManager; -import org.ultramine.permission.IPermission; -import org.ultramine.permission.IPermissionHandler; -import org.ultramine.permission.MetaResolver; -import org.ultramine.permission.Permission; +import net.minecraft.server.MinecraftServer; +import org.ultramine.permission.IPermissionManager; import org.ultramine.permission.PermissionRepository; -import org.ultramine.permission.ServerPermissionManager; +import org.ultramine.permission.internal.UserContainer; -import java.util.List; -import java.util.Set; - -public class PermissionHandler implements IPermissionHandler +public class PermissionHandler implements IPermissionManager { - public static final String OP_PERMISSION = "minecraft.op"; - - private static PermissionHandler instance; - private static PermissionRepository mainRepository = new PermissionRepository(); - - public static void registerPermission(String key, String name, String description) - { - if (instance != null) - getInstance().getRepository().registerPermission(new Permission(key, name, description)); - else - mainRepository.registerPermission(new Permission(key, name, description)); - } - - public static void registerPermission(IPermission permission) - { - if (instance != null) - getInstance().getRepository().registerPermission(permission); - else - mainRepository.registerPermission(permission); - } - - public static PermissionRepository.ProxyPermission getPermission(String key) - { - if (instance != null) - return getInstance().getRepository().getPermission(key); - - return mainRepository.getPermission(key); - } - - public static void initServer() - { - if (instance != null) - throw new IllegalStateException("Handler is already initialized"); - instance = new PermissionHandler(new ServerPermissionManager(ConfigurationHandler.getSettingDir(), new PermissionRepository(mainRepository))); - } - - public static void initClient() - { - if (instance != null) - throw new IllegalStateException("Handler is already initialized"); - instance = new PermissionHandler(new ClientPermissionManager(new PermissionRepository(mainRepository))); - } - - public static void reset() - { - instance = null; - } + private static PermissionHandler instance = new PermissionHandler(); public static PermissionHandler getInstance() { - if (instance == null) - throw new IllegalStateException("Handler is not initialized"); return instance; } - private IPermissionHandler handler; - - private PermissionHandler(IPermissionHandler handler) + private IPermissionManager getHandler() { - this.handler = handler; + return MinecraftServer.getServer().getPermissionManager(); } @Override public boolean has(String world, String player, String permission) { - return handler.has(world, player, permission); + return getHandler().has(world, player, permission); } public boolean has(ICommandSender player, String permission) @@ -87,17 +31,30 @@ return has(worldName(player), player.getCommandSenderName(), permission); } - public boolean has(ICommandSender player, List permissions) + public boolean has(ICommandSender player, String... permissions) { + if (permissions == null) + return true; + for (String permission : permissions) if (!has(player, permission)) return false; return true; } + public boolean hasAny(ICommandSender player, String... permissions) + { + if (permissions == null) + return true; + + for (String permission : permissions) + if (has(player, permission)) return true; + return false; + } + @Override public void add(String world, String player, String permission) { - handler.add(world, player, permission); + getHandler().add(world, player, permission); } public void add(ICommandSender player, String permission) @@ -106,15 +63,21 @@ } @Override - public void add(String world, String permission) + public void addToWorld(String world, String permission) { - handler.add(world, permission); + getHandler().addToWorld(world, permission); + } + + @Override + public void addToGroup(String group, String permission) + { + getHandler().addToGroup(group, permission); } @Override public void remove(String world, String player, String permission) { - handler.remove(world, player, permission); + getHandler().remove(world, player, permission); } public void remove(ICommandSender player, String permission) @@ -123,55 +86,67 @@ } @Override - public void remove(String world, String permission) + public void removeFromWorld(String world, String permission) { - handler.remove(world, permission); + getHandler().removeFromWorld(world, permission); } @Override - public MetaResolver getMeta(String world, String player) + public void removeFromGroup(String group, String permission) { - return handler.getMeta(world, player); - } - - public MetaResolver getMeta(ICommandSender player) - { - return getMeta(worldName(player), player.getCommandSenderName()); + getHandler().removeFromGroup(group, permission); } @Override - public void setMeta(String world, String player, String key, Object value) + public String getMeta(String world, String player, String key) { - handler.setMeta(world, player, key, value); + return getHandler().getMeta(world, player, key); } - public void setMeta(ICommandSender player, String key, Object value) + public String getMeta(ICommandSender player, String key) + { + return getMeta(worldName(player), player.getCommandSenderName(), key); + } + + @Override + public void setMeta(String world, String player, String key, String value) + { + getHandler().setMeta(world, player, key, value); + } + + @Override + public void setGroupMeta(String group, String key, String value) + { + getHandler().setGroupMeta(group, key, value); + } + + public void setMeta(ICommandSender player, String key, String value) { setMeta(worldName(player), player.getCommandSenderName(), key, value); } @Override - public Set findUsersWithPermission(String world, String permission) - { - return handler.findUsersWithPermission(world, permission); - } - - @Override public void save() { - handler.save(); + getHandler().save(); } @Override public void reload() { - handler.reload(); + getHandler().reload(); } @Override public PermissionRepository getRepository() { - return handler.getRepository(); + return getHandler().getRepository(); + } + + @Override + public UserContainer getWorldContainer(String world) + { + return getHandler().getWorldContainer(world); } private String worldName(ICommandSender player) diff --git a/src/main/java/org/ultramine/server/UltramineServerModContainer.java b/src/main/java/org/ultramine/server/UltramineServerModContainer.java index e82c8c2..f43619a 100644 --- a/src/main/java/org/ultramine/server/UltramineServerModContainer.java +++ b/src/main/java/org/ultramine/server/UltramineServerModContainer.java @@ -19,6 +19,8 @@ import cpw.mods.fml.common.network.NetworkCheckHandler; import cpw.mods.fml.common.network.NetworkRegistry; import cpw.mods.fml.relauncher.Side; +import org.ultramine.commands.syntax.DefaultCompleters; +import org.ultramine.permission.commands.BasicPermissionCommands; public class UltramineServerModContainer extends DummyModContainer { @@ -48,7 +50,6 @@ public void preInit(FMLPreInitializationEvent e) { ConfigurationHandler.load(); - PermissionHandler.registerPermission(PermissionHandler.OP_PERMISSION, "Op", "Standard minecraft op permissions"); } @Subscribe @@ -80,21 +81,13 @@ @Subscribe public void serverStarting(FMLServerStartingEvent e) { - switch (e.getSide()) - { - case CLIENT: - PermissionHandler.initClient(); - break; - case SERVER: - PermissionHandler.initServer(); - break; - } + e.registerArgumentHandlers(DefaultCompleters.class); + e.registerCommands(BasicPermissionCommands.class); } @Subscribe public void stopServer(FMLServerStoppedEvent e) { - PermissionHandler.reset(); } @Override diff --git a/src/main/java/org/ultramine/server/util/OpPermissionProxySet.java b/src/main/java/org/ultramine/server/util/OpPermissionProxySet.java index 8835a39..d97a4e9 100644 --- a/src/main/java/org/ultramine/server/util/OpPermissionProxySet.java +++ b/src/main/java/org/ultramine/server/util/OpPermissionProxySet.java @@ -1,5 +1,6 @@ package org.ultramine.server.util; +import org.ultramine.permission.internal.ServerPermissionManager; import org.ultramine.server.PermissionHandler; import java.util.Collection; @@ -12,6 +13,8 @@ @Deprecated public class OpPermissionProxySet implements Set { + public static final String OP_PERMISSION = "minecraft.op"; + @Override public int size() { @@ -51,14 +54,14 @@ @Override public boolean add(String s) { - PermissionHandler.getInstance().add("global", s, PermissionHandler.OP_PERMISSION); + PermissionHandler.getInstance().add("global", s, OP_PERMISSION); return true; } @Override public boolean remove(Object o) { - PermissionHandler.getInstance().remove("global", o.toString(), PermissionHandler.OP_PERMISSION); + PermissionHandler.getInstance().remove("global", o.toString(), OP_PERMISSION); return true; } @@ -106,6 +109,7 @@ private Set ops() { - return PermissionHandler.getInstance().findUsersWithPermission("global", PermissionHandler.OP_PERMISSION); + return PermissionHandler.getInstance() + .getWorldContainer(ServerPermissionManager.GLOBAL_WORLD).getAllWithPermission(OP_PERMISSION); } } diff --git a/src/main/resources/assets/ultramine/lang/en_US.lang b/src/main/resources/assets/ultramine/lang/en_US.lang new file mode 100644 index 0000000..f36faf9 --- /dev/null +++ b/src/main/resources/assets/ultramine/lang/en_US.lang @@ -0,0 +1,24 @@ +# Permissions +command.permissions.serverworld=You must specify world when using this command from console + +command.pconfig.usage=/pconfig +command.pconfig.description=Save or reload all permissions configs +command.pconfig.success.save=Permissions are saved +command.pconfig.success.reload=Permissions are reloaded + +command.pworld.usage=/pworld [world] +command.pworld.description=Add or remove permissions to all user in world (current is default) +command.pworld.success.add=Add permission <%s> to world <%s> +command.pworld.success.remove=Remove permission <%s> from world <%s> + +command.puser.usage=/puser [world] OR /puser [world] meta +command.puser.description=Add/remove permissions OR set meta for user in world (current is default) +command.puser.success.add=Add permission <%s> to user <%s> in world <%s> +command.puser.success.remove=Remove permission <%s> from user <%s> in world <%s> +command.puser.success.meta=Set meta <%s> to <%s> for user <%s> in world <%s> + +command.pgroup.usage=/pgroup OR /pgroup meta +command.pgroup.description=Add/remove permissions OR set meta for group +command.pgroup.success.add=Add permission <%s> to group <%s> +command.pgroup.success.remove=Remove permission <%s> from group <%s> +command.pgroup.success.meta=Set meta <%s> to <%s> for group <%s> \ No newline at end of file diff --git a/src/test/groovy/org/ultramine/commands/syntax/ArgumentsPatternParserTest.groovy b/src/test/groovy/org/ultramine/commands/syntax/ArgumentsPatternParserTest.groovy new file mode 100644 index 0000000..31f43c4 --- /dev/null +++ b/src/test/groovy/org/ultramine/commands/syntax/ArgumentsPatternParserTest.groovy @@ -0,0 +1,121 @@ +package org.ultramine.commands.syntax + +import spock.lang.Specification + +class ArgumentsPatternParserTest extends Specification { + + def parser = new ArgumentsPatternParser() + + def "Test single handler"() { + setup: + def argumentHandler = Mock(IArgumentCompletionHandler) + parser.registerHandler("test", argumentHandler) + def commandHandler = parser.parse("") + + when: "Get completion" + commandHandler.getCompletionOptions("first") + + then: "Argument handler is called" + 1 * argumentHandler.handleCompletion("first", "par1", "par2") + } + + def "Test not registered handler"() { + setup: + def argumentHandler = Mock(IArgumentCompletionHandler) + parser.registerHandler("test", argumentHandler) + def commandHandler = parser.parse("") + + when: "Get completion" + commandHandler.getCompletionOptions("first") + + then: "Argument handler is not called" + 0 * argumentHandler._ + } + + def "Test action argument"() { + setup: + def commandHandler = parser.parse("[ add remove ]") + + expect: "Action is parsed" + commandHandler.getCompletionOptions("a") == ["add"] + commandHandler.resolveActionName("add") == "add" + } + + def "Test several arguments"() { + setup: + def playerHandler = Mock(IArgumentCompletionHandler) + def itemHandler = Mock(IArgumentCompletionHandler) + parser.registerHandler("player", playerHandler) + parser.registerHandler("item", itemHandler) + def commadHandler = parser.parse(string) + + when: "Get completions" + commadHandler.getCompletionOptions("first") + commadHandler.getCompletionOptions("first", "second") + commadHandler.getCompletionOptions("first", "second", "third") + commadHandler.getCompletionOptions("first", "second", "third", "fourth") + + then: "Argument handles called correctly" + 1 * playerHandler.handleCompletion("first") + 1 * itemHandler.handleCompletion("third", "first") + 0 * playerHandler._ + 0 * itemHandler._ + + where: + string << [" <> ", " < player> < > < item &0 >"] + } + + def "Test infinite"() { + setup: + def argumentHandler = Mock(IArgumentCompletionHandler) + parser.registerHandler("test", argumentHandler) + def commandHandler = parser.parse("<> ...") + + when: "Get completion" + commandHandler.getCompletionOptions("first", "second", "third") + + then: "Argument handler is called" + 1 * argumentHandler.handleCompletion("third", "par1", "par2") + } + + def "Test naming"() { + setup: + parser.registerHandler("test", Mock(IArgumentCompletionHandler)) + def commandHandler = parser.parse(" [add remove] <%p3>") + + expect: "Names are correct" + commandHandler.getArgumentsNames() == ["p1", "test", null, "p2", "p3"] + } + + def "Test integration"() { + setup: + def commnadHander = parser.parse(" ") + parser.registerHandlers(TestHandlers) + + expect: + commnadHander.getCompletionOptions("B") == ["Bob", "Barny"] + commnadHander.getCompletionOptions("Bob", "ki") == ["kick", "kill"] + commnadHander.match("Jenifer", "aza") + commnadHander.isUsernameIndex(0) + } + + public static class TestHandlers { + @ArgumentCompleter(value = "player", isUsername = true) + public static List player(String val, String[] args) + { + return ["Bob", "Jenifer", "Barny"].findAll { it.startsWith(val) } + } + + @ArgumentCompleter("list") + public static List list(String val, String[] args) + { + return args.findAll { it.startsWith(val) } + } + + @ArgumentValidator("player") + public static boolean player_v(String val, String[] args) + { + return ["Bob", "Jenifer", "Barny"].contains(val) + } + } +} diff --git a/src/test/groovy/org/ultramine/commands/syntax/ArgumentsPatternTest.groovy b/src/test/groovy/org/ultramine/commands/syntax/ArgumentsPatternTest.groovy new file mode 100644 index 0000000..1b29a06 --- /dev/null +++ b/src/test/groovy/org/ultramine/commands/syntax/ArgumentsPatternTest.groovy @@ -0,0 +1,190 @@ +package org.ultramine.commands.syntax + +import spock.lang.Specification + +import static org.ultramine.commands.syntax.ArgumentsPattern.MatchResult.* + +class ArgumentsPatternTest extends Specification { + + def builder = new ArgumentsPattern.Builder() + def pattern = builder.build(); + + def "Test completion"() { + setup: "Pattern with argument" + def argument = Mock(IArgument) + builder.addArgument("name", argument); + + when: "Get completion for first argument" + pattern.getCompletionOptions("first") + + then: "Argument handler is called" + 1 * argument.getCompletionOptions("first") + } + + def "Test action completion"() { + setup: "Pattern with action" + builder.addAction("add", "adopt", "remove") + + expect: + pattern.getCompletionOptions("ad") == ["add", "adopt"] + } + + def "Test action name"() { + setup: "Pattern without action" + builder.addArgument("name", Mock(IArgument)) + + expect: "Action name is blank" + pattern.resolveActionName("name") == "" + + when: "With one action" + builder.addAction("add", "get") + + then: "Action name is correct" + pattern.resolveActionName("name", "add") == "add" + + when: "With two actions" + builder.addAction("make") + + then: "Space is separator between actions" + pattern.resolveActionName("name", "get", "make") == "get make" + } + + def "Test infinite handler"() { + setup: + def argument = Mock(IArgument) + builder.addArgument("name", argument) + + when: "Get completion for second argument" + def result = pattern.getCompletionOptions("first", "second") + + then: "Argument handler is not called" + 0 * argument._ + + and: "Result is null" + result == null + + when: "Make command handler infinite" + builder.makeInfinite() + + and: "Get completion for second and third argument" + pattern.getCompletionOptions("first", "second") + pattern.getCompletionOptions("first", "second", "third") + + then: "Argument handler is called" + 1 * argument.getCompletionOptions("first", "second") + 1 * argument.getCompletionOptions("first", "second", "third") + } + + def "Test username argument"() { + setup: "Command completion with username argument" + builder.addArgument("name", Mock(IArgument)) + builder.addArgument("name", Mock(IArgument) { + isUsername() >> true + }) + builder.addArgument("name", Mock(IArgument)) + + expect: "Username argument is detected correctly" + !pattern.isUsernameIndex(0) + pattern.isUsernameIndex(1) + !pattern.isUsernameIndex(2) + + when: "Add another username argument" + builder.addArgument("name", Mock(IArgument) { + isUsername() >> true + }) + + then: "Both arguments are detected" + !pattern.isUsernameIndex(0) + pattern.isUsernameIndex(1) + !pattern.isUsernameIndex(2) + pattern.isUsernameIndex(3) + } + + def "Test blank handler"() { + expect: "Always return null" + pattern.getCompletionOptions("first") == null + pattern.getCompletionOptions("first", "second") == null + } + + def "Test matching"() { + setup: + builder.addArgument("name", Mock(IArgument)) + builder.addAction("add") + builder.addArgument("name", Mock(IArgument)) + + expect: "Matching is correct" + !pattern.match("arg1") + !pattern.match("arg1", "add") + pattern.match("arg1", "add", "arg2") + !pattern.match("arg1", "add2", "arg2") + !pattern.match("arg1", "add", "arg2", "arg3") + + when: "Make handler infinite" + builder.makeInfinite() + + then: "Matching is correct" + !pattern.match("arg1") + !pattern.match("arg1", "add") + pattern.match("arg1", "add", "arg2") + !pattern.match("arg1", "ad", "arg2") + pattern.match("arg1", "add", "arg2", "arg3") + } + + def "Test partial matching"() + { + setup: + builder.addArgument("name", Mock(IArgument)) + builder.addAction("add") + builder.addArgument("name", Mock(IArgument)) + + expect: "Partial matching is correct" + pattern.partialMatch("arg1") == POSSIBLY + pattern.partialMatch("arg1", "add") == FULLY + pattern.partialMatch("arg1", "add", "arg2") == FULLY + pattern.partialMatch("arg1", "add2", "arg2") == NOT + pattern.partialMatch("arg1", "add", "arg2", "arg3") == NOT + + when: "Make handler infinite" + builder.makeInfinite() + + then: "Partial matching is correct" + pattern.partialMatch("arg1") == POSSIBLY + pattern.partialMatch("arg1", "add") == FULLY + pattern.partialMatch("arg1", "add", "arg2") == FULLY + pattern.partialMatch("arg1", "ad", "arg2") == NOT + pattern.partialMatch("arg1", "add", "arg2", "arg3") == FULLY + } + + def "Test names"() { + setup: + builder.addArgument("ignored", Mock(IArgument)) + builder.addAction("add") + builder.addArgument("name", Mock(IArgument)) + + expect: "Names are correct" + pattern.getArgumentsNames() == ["ignored", null, "name"] + } + + def "Test integration"() { + setup: + builder.addArgument("name", Mock(IArgument)) + IArgument argument = new HandlerBasedArgument("name", "boom", "bod", "&0"); + argument.setCompletionHandler(new IArgumentCompletionHandler() { + @Override + List handleCompletion(String val, String[] params) { + return params.findAll { it.startsWith(val) } + } + + @Override + boolean isUsername() { + return false + } + }) + builder.addArgument("name", argument) + + expect: "Completions are correct" + pattern.getCompletionOptions("ara", "bo") == ["boom", "bod"] + pattern.getCompletionOptions("zava", "za") == ["zava"] + pattern.getCompletionOptions("b", "va", "vaka") == null + } +} diff --git a/src/test/groovy/org/ultramine/commands/syntax/HandlerBasedArgumentTest.groovy b/src/test/groovy/org/ultramine/commands/syntax/HandlerBasedArgumentTest.groovy new file mode 100644 index 0000000..f66183e --- /dev/null +++ b/src/test/groovy/org/ultramine/commands/syntax/HandlerBasedArgumentTest.groovy @@ -0,0 +1,46 @@ +package org.ultramine.commands.syntax + +import spock.lang.Specification + +class HandlerBasedArgumentTest extends Specification { + + + def "Test argument replacement"() { + setup: + def argument = new HandlerBasedArgument("name", "p1", "&0", "p3") + def handler = Mock(IArgumentCompletionHandler) + argument.setCompletionHandler(handler) + + when: "Get completion for argument" + argument.getCompletionOptions("first", "second") + + then: "Argument handler is called with right params" + 1 * handler.handleCompletion("second", "p1", "first", "p3") + } + + def "Test argument replacement: out if bound index"() { + setup: + def argument = new HandlerBasedArgument("name", "p1", "&5", "p3") + def handler = Mock(IArgumentCompletionHandler) + argument.setCompletionHandler(handler) + + when: "Get completion for argument" + argument.getCompletionOptions("first", "second") + + then: "Argument handler is called with right params" + 1 * handler.handleCompletion("second", "p1", "", "p3") + } + + def "Test argument replacement: not number"() { + setup: + def argument = new HandlerBasedArgument("name", "p1", "&aza", "p3") + def handler = Mock(IArgumentCompletionHandler) + argument.setCompletionHandler(handler) + + when: "Get completion for argument" + argument.getCompletionOptions("first", "second") + + then: "Argument handler is called with right params" + 1 * handler.handleCompletion("second", "p1", "&aza", "p3") + } +} diff --git a/src/test/groovy/org/ultramine/permission/GroupPermissionTest.groovy b/src/test/groovy/org/ultramine/permission/GroupPermissionTest.groovy index e3331cb..047e767 100644 --- a/src/test/groovy/org/ultramine/permission/GroupPermissionTest.groovy +++ b/src/test/groovy/org/ultramine/permission/GroupPermissionTest.groovy @@ -22,8 +22,8 @@ !group2.isDirty() and: "Both groups have own meta" - group1.getMeta().getString("m1") - group2.getMeta().getString("m2") + group1.getMeta("m1") + group2.getMeta("m2") } def "Test dirty notification"() { @@ -43,44 +43,34 @@ def "Test subscribing to permission changes"() { setup: - def sPerm = Mock(IPermission) { getKey() >> "p" } - def cPerm = Mock(IChangeablePermission) { getKey() >> "c" } + def permission = Mock(IPermission) { getKey() >> "c" } def group = new GroupPermission("group.test") - when: "Add permissions to group" - group.addPermission(sPerm) - group.addPermission(cPerm) + when: "Add permission to group" + group.addPermission(permission) - then: "Group subscribes to IChangeablePermission" - 1 * cPerm.subscribe(group) - 0 * sPerm.subscribe(_) + then: "Group subscribes to permission" + 1 * permission.subscribe(group) - when: "Remove permissions from group" - group.removePermission(sPerm) - group.removePermission(cPerm) + when: "Remove permission from group" + group.removePermission(permission) - then: "Group unsubscribes to IChangeablePermission" - 1 * cPerm.unsubscribe(group) - 0 * sPerm.unsubscribe(_) + then: "Group unsubscribes to permission" + 1 * permission.unsubscribe(group) } def "Test meta parsing"() { setup: def group = new GroupPermission("group.test", [ - name: "Test1", - description: "Test2", - priority: 200, + priority: "200", perfix: "Test3" ]) expect: group.getKey() == "group.test" - group.getName() == "Test1" - group.getDescription() == "Test2" group.getPriority() == 200 - group.getMeta().getString("perfix") == "Test3" - group.getMeta().getString("asd") == "" - group.getMeta().getInt("dsa") == 0 + group.getMeta("perfix") == "Test3" + group.getMeta("asd") == "" } def "Test blank group"() { @@ -89,8 +79,6 @@ expect: group.getKey() == "group.test" - group.getName() == "group.test" - group.getDescription() == "" group.getPriority() == 0 } } diff --git a/src/test/groovy/org/ultramine/permission/NegativePermissionTest.groovy b/src/test/groovy/org/ultramine/permission/NegativePermissionTest.groovy index c548bab..ac0f759 100644 --- a/src/test/groovy/org/ultramine/permission/NegativePermissionTest.groovy +++ b/src/test/groovy/org/ultramine/permission/NegativePermissionTest.groovy @@ -1,6 +1,9 @@ package org.ultramine.permission -import static org.ultramine.permission.PermissionResolver.CheckResult.* +import org.ultramine.permission.internal.MetaResolver +import org.ultramine.permission.internal.PermissionResolver + +import static org.ultramine.permission.internal.CheckResult.* import spock.lang.Specification /** @@ -12,69 +15,25 @@ setup: IPermission permission = Mock(IPermission) { getKey() >> "test.key" - getName() >> "Test Name" - getDescription() >> "Test Description" - getPriority() >> 100 - getPermissions() >> PermissionResolver.createForKey("test.key", 1) + getMeta("aza") >> "aza" + check("aza") >> TRUE } when: "Create new NegativePermission" - def perm = new NegativePermission(permission) + def perm = new NegativePermission("^test.key", permission) then: "PermissionResolver was inverted" perm.getKey() == "^test.key" - perm.getName() == "NOT: Test Name" - perm.getDescription() == "NOT: Test Description" - perm.getPriority() == 100 - perm.getPermissions().check("test.key") == FALSE + perm.getMeta("aza") == "" + perm.check("aza") == FALSE } - def "Test subscribe/unsubscribe IPermission"() { + def "Test subscribe/unsubscribe permission"() { setup: IPermission permission = Mock(IPermission) def listener = Mock(IDirtyListener) - def perm = new NegativePermission(permission) - - when: "Try to subscribe/unsubscribe listener" - perm.subscribe(listener) - perm.unsubscribe(listener) - - then: "No interaction were done" - 0 * permission._ - 0 * listener._ - } - - def "Test wrap IChangeablePermission"() { - setup: "Create new NegativePermission" - IPermission permission = Mock(IChangeablePermission) { - getKey() >> "test.key" - getName() >> "Test Name" - getDescription() >> "Test Description" - getPriority() >> 100 - getPermissions() >> PermissionResolver.createForKey("test.key", 1) - } - - when: "Create new NegativePermission" - def perm = new NegativePermission(permission) - - then: "PermissionResolver was inverted" - perm.getKey() == "^test.key" - perm.getName() == "NOT: Test Name" - perm.getDescription() == "NOT: Test Description" - perm.getPriority() == 100 - perm.getPermissions().check("test.key") == FALSE - - and: "Subscribed to permission" - 1 * permission.subscribe(_) - } - - def "Test subscribe/unsubscribe IChangeablePermission"() { - setup: - IPermission permission = Mock(IChangeablePermission) - - def listener = Mock(IDirtyListener) - def perm = new NegativePermission(permission) + def perm = new NegativePermission("key", permission) when: "Try to subscribe/unsubscribe listener" perm.subscribe(listener) @@ -86,44 +45,31 @@ 0 * listener._ } - def "Test blank description"() { - setup: "Permission with blank description" - IPermission permission = Mock(IChangeablePermission) { - getDescription() >> "" - } - - when: "Create new NegativePermission" - def perm = new NegativePermission(permission) - - then: "Description is blank" - perm.getDescription() == "" - } - def "Test blank meta"() { when: "Create new NegativePermission" - def perm = new NegativePermission(Mock(IPermission)) + def perm = new NegativePermission("per", Mock(IPermission)) then: "Description is blank" - perm.getMeta() == MetaResolver.BLANK_RESOLVER + perm.getMeta("za") == "" } def "Test integration with group permission"() { setup: def group = new GroupPermission("group") - group.addPermission(new Permission("p1")) + group.addPermission(new DummyPermission("p1")) when: "Create negative permission" - def perm = new NegativePermission(group) + def perm = new NegativePermission("key", group) then: "Negative permission contains group permissions" - perm.getPermissions().check("p1") == FALSE + perm.check("p1") == FALSE when: "Group permission updates" - group.addPermission(new Permission("p2")) + group.addPermission(new DummyPermission("p2")) then: "Negative permission also updates" - perm.getPermissions().check("p1") == FALSE - perm.getPermissions().check("p2") == FALSE + perm.check("p1") == FALSE + perm.check("p2") == FALSE } } diff --git a/src/test/groovy/org/ultramine/permission/PermissionHolderTest.groovy b/src/test/groovy/org/ultramine/permission/PermissionHolderTest.groovy index 7c35bf8..5e1f01b 100644 --- a/src/test/groovy/org/ultramine/permission/PermissionHolderTest.groovy +++ b/src/test/groovy/org/ultramine/permission/PermissionHolderTest.groovy @@ -1,8 +1,13 @@ package org.ultramine.permission +import org.ultramine.permission.internal.MetaResolver +import org.ultramine.permission.internal.PermissionHolder +import org.ultramine.permission.internal.PermissionResolver import spock.lang.Specification -import static org.ultramine.permission.PermissionResolver.CheckResult.UNRESOLVED +import static org.ultramine.permission.internal.CheckResult.FALSE +import static org.ultramine.permission.internal.CheckResult.TRUE +import static org.ultramine.permission.internal.CheckResult.UNRESOLVED class PermissionHolderTest extends Specification { @@ -15,22 +20,28 @@ def "Test calculation"() { setup: - def resolver = Mock(PermissionResolver) - def perm1 = Mock(IPermission) { + def spy = Spy(PermissionResolver) + def perm1 = Stub(IPermission) { getKey() >> "p.1" - getPermissions() >> resolver - getMeta() >> createMetaResolver([test1: "1", test2: "1", test3: "1"]) - getPriority() >> 1 + mergeMetaTo(_) >> { MetaResolver resolver -> + resolver.merge([test1: "1", test2: "1", test3: "1"], 1) + } + mergePermissionsTo(_) >> { PermissionResolver resolver -> + resolver.merge([test1: true, test2: true], 1) + } } - def perm2 = Mock(IPermission) { + def perm2 = Stub(IPermission) { getKey() >> "p.2" - getPermissions() >> resolver - getMeta() >> createMetaResolver([test2: "2"]) - getPriority() >> 2 + mergeMetaTo(_) >> { MetaResolver resolver -> + resolver.merge([test2: "2"], 2) + } + mergePermissionsTo(_) >> { PermissionResolver resolver -> + resolver.merge([test2: false], 2) + } } def holder = new PermissionHolder([test1: "0"]) - holder.permissionResolver = resolver + holder.permissionResolver = spy holder.addPermission(perm1) holder.addPermission(perm2) @@ -39,46 +50,50 @@ then: "Permissions are calculated" !holder.isDirty() - 1 * resolver.clear() - 1 * resolver.merge(resolver, 1) - 1 * resolver.merge(resolver, 2) - 0 * resolver._ + holder.check("test1") == TRUE + holder.check("test2") == FALSE + holder.check("test3") == UNRESOLVED and: "Meta is correct" - holder.getMeta().getString("test1") == "0" - holder.getMeta().getString("test2") == "2" - holder.getMeta().getString("test3") == "1" + holder.getMeta("test1") == "0" + holder.getMeta("test2") == "2" + holder.getMeta("test3") == "1" when: "Calculate one more time" holder.calculate() then: "Nothing happens" !holder.isDirty() - 0 * resolver._ + 0 * spy._ } def "Test clearPermissions"() { setup: - def perm = Mock(IChangeablePermission) { + def perm = Mock(IPermission) { getKey() >> "p1" - getPermissions() >> PermissionResolver.createForKey("p1", 0) - getMeta() >> createMetaResolver([p1: 1]) + mergeMetaTo(_) >> { MetaResolver resolver -> + resolver.merge([test2: "1"], 0) + } + mergePermissionsTo(_) >> { PermissionResolver resolver -> + resolver.merge([test2: true], 0) + } } - def holder = new PermissionHolder([a: 1, b: 2]) - holder.addPermission(new Permission("p2")) + def holder = new PermissionHolder([a: "1", b: "2"]) + holder.addPermission(new DummyPermission("p2")) holder.addPermission(perm) + holder.calculate() when: "Clear holder's permissions" holder.clearPermissions() then: "It contains only inner meta" - !holder.getMeta().getInt("p1") - holder.getMeta().getInt("a") == 1 - holder.getMeta().getInt("b") == 2 + !holder.getMeta("test2") + holder.getMeta("a") == "1" + holder.getMeta("b") == "2" and: "It contains no permissions" - holder.getPermissions().check("p1") == UNRESOLVED - holder.getPermissions().check("p2") == UNRESOLVED + holder.check("test2") == UNRESOLVED + holder.check("p2") == UNRESOLVED and: "It unsubscribed from all permissions" 1 * perm.unsubscribe(holder) @@ -86,26 +101,30 @@ def "Test clearMeta"() { setup: - def perm = Mock(IChangeablePermission) { + def perm = Mock(IPermission) { getKey() >> "p1" - getPermissions() >> PermissionResolver.createForKey("p1", 0) - getMeta() >> createMetaResolver([p1: 1]) + mergeMetaTo(_) >> { MetaResolver resolver -> + resolver.merge([test2: "1"], 0) + } + mergePermissionsTo(_) >> { PermissionResolver resolver -> + resolver.merge([test2: true], 0) + } } - def holder = new PermissionHolder([a: 1, b: 2]) - holder.addPermission(new Permission("p2")) + def holder = new PermissionHolder([a: "1", b: "2"]) + holder.addPermission(new DummyPermission("p2")) holder.addPermission(perm) when: "Clear holder's meta" holder.clearMeta() then: "It contains only permission's meta" - holder.getMeta().getInt("p1") == 1 - !holder.getMeta().getInt("a") - !holder.getMeta().getInt("b") + holder.getMeta("test2") == "1" + !holder.getMeta("a") + !holder.getMeta("b") and: "It contains all permissions" - holder.getPermissions().check("p1") != UNRESOLVED - holder.getPermissions().check("p2") != UNRESOLVED + holder.check("test2") != UNRESOLVED + holder.check("p2") != UNRESOLVED and: "It did not unsubscribe from all permissions" 0 * perm.unsubscribe(holder) @@ -129,7 +148,7 @@ when: "Call setMeta method" holder.calculate() - holder.setMeta("test", 21) + holder.setMeta("test", "21") then: "Group becomes dirty" 1 * holder.makeDirty() @@ -143,7 +162,7 @@ when: "Call addPermission method" holder.calculate() - holder.addPermission(new Permission("test")) + holder.addPermission(new DummyPermission("test")) then: "Group becomes dirty" 1 * holder.makeDirty() diff --git a/src/test/groovy/org/ultramine/permission/PermissionRepositoryTest.groovy b/src/test/groovy/org/ultramine/permission/PermissionRepositoryTest.groovy index 0c73425..674c8f3 100644 --- a/src/test/groovy/org/ultramine/permission/PermissionRepositoryTest.groovy +++ b/src/test/groovy/org/ultramine/permission/PermissionRepositoryTest.groovy @@ -3,85 +3,56 @@ import org.spockframework.mock.MockDetector import spock.lang.Specification -import static org.ultramine.permission.PermissionRepository.ProxyPermission.ProxyType.* -import static org.ultramine.permission.PermissionResolver.CheckResult.FALSE -import static org.ultramine.permission.PermissionResolver.CheckResult.TRUE -import static org.ultramine.permission.PermissionResolver.CheckResult.UNRESOLVED +import static org.ultramine.permission.internal.CheckResult.FALSE +import static org.ultramine.permission.internal.CheckResult.TRUE +import static org.ultramine.permission.internal.CheckResult.UNRESOLVED class PermissionRepositoryTest extends Specification { + def repository = new PermissionRepository() + def "Test get proxy permission"() { setup: def detector = new MockDetector() def perm = Mock(IPermission) { getKey() >> "key" - getName() >> "test" + getMeta(_) >> "test" } - def repository = new PermissionRepository() when: "Try to get not registered permission" def proxy = repository.getPermission("key") then: "Returned proxy of dummy permission" - proxy.getWrappedPermission().class == Permission - proxy.getType() == DUMMY - proxy.getName() == "key" + proxy.getWrappedPermission().class == DummyPermission + proxy.isDummy(); + proxy.getMeta("") == "" when: "Register this permission" repository.registerPermission(perm) then: "Proxy linked to added permission" detector.isMock(proxy.getWrappedPermission()) - proxy.getType() != DUMMY - proxy.getName() == "test" + !proxy.isDummy() + proxy.getMeta("") == "test" } def "Test registration of existed permission"() { - setup: - def repository = new PermissionRepository() when: "Register permission same key twice" - repository.registerPermission(Mock(IPermission) { getKey() >> "key"; getName() >> "1" }) - repository.registerPermission(Mock(IPermission) { getKey() >> "key"; getName() >> "2" }) + repository.registerPermission(Mock(IPermission) { getKey() >> "key"; getMeta(_) >> "1" }) + repository.registerPermission(Mock(IPermission) { getKey() >> "key"; getMeta(_) >> "2" }) then: "Exception is thrown" thrown(IllegalArgumentException) and: "First permission is not overwritten" - repository.getPermission("key").getName() == "1" + repository.getPermission("key").getMeta("") == "1" } def "Test proxy of IPermission"() { setup: def listener = Mock(IDirtyListener) def perm = Mock(IPermission) { getKey() >> "key" } - def repository = new PermissionRepository() - - when: "Listener is subscribed to proxy permission" - def proxy = repository.getPermission("key") - proxy.subscribe(listener) - - and: "And IPermission is registered" - repository.registerPermission(perm) - - then: "Listener is notified" - 1 * listener.makeDirty() - - and: "Proxy type is SIMPLE" - proxy.getType() == SIMPLE - - when: "Add another lister" - proxy.subscribe(Mock(IDirtyListener)) - - then: "noting is happened" - 0 * perm._ - } - - def "Test proxy of IChangeablePermission"() { - setup: - def listener = Mock(IDirtyListener) - def perm = Mock(IChangeablePermission) { getKey() >> "key" } - def repository = new PermissionRepository() when: "Listener is subscribed to proxy permission" def proxy = repository.getPermission("key") @@ -93,8 +64,8 @@ then: "Listener is notified" 1 * listener.makeDirty() - and: "Proxy type is CHANGEABLE" - proxy.getType() == CHANGEABLE + and: "Proxy is not Dummy" + !proxy.isDummy() and: "Listener is passed to permission" 1 * perm.subscribe(listener) @@ -115,15 +86,14 @@ def "Test proxy unsubscribe"() { setup: def listener = Mock(IDirtyListener) - def perm = Mock(IChangeablePermission) { getKey() >> "key" } - def repository = new PermissionRepository() + def perm = Mock(IPermission) { getKey() >> "key" } when: "Listener is subscribed and unsubscribe to proxy permission" def proxy = repository.getPermission("key") proxy.subscribe(listener) proxy.unsubscribe(listener) - and: "And IChangeablePermission is registered" + and: "And permission is registered" repository.registerPermission(perm) then: "0 listener passed to proxy" @@ -131,8 +101,6 @@ } def "Test negative key"() { - setup: - def repository = new PermissionRepository() when: "Try to get permission with negative key" def perm = repository.getPermission("^group.admin") @@ -141,13 +109,11 @@ perm.class == NegativePermission and: "Negative permission linked to proxy" - perm.getWrappedPermission().getName() == "group.admin" - perm.getWrappedPermission().getType() == DUMMY + perm.getWrappedPermission().getKey() == "group.admin" + perm.getWrappedPermission().class == PermissionRepository.ProxyPermission } def "Test registre ^* permission"() { - setup: - def repository = new PermissionRepository() when: "Try to register ^* permission" repository.registerPermission(Mock(IPermission) { getKey() >> "^test" }) @@ -158,7 +124,6 @@ def "Test integration"() { setup: - def repository = new PermissionRepository(); def group1 = new GroupPermission("group1") group1.addPermission(repository.getPermission("p1")) group1.addPermission(repository.getPermission("group2")) @@ -168,19 +133,19 @@ def perm = repository.getPermission("^group1") then: "Negative permission contains group1 permissions" - perm.getPermissions().check("p1") == FALSE - perm.getPermissions().check("p2") == UNRESOLVED - perm.getPermissions().check("group2") == FALSE - perm.getPermissions().check("p3") == UNRESOLVED + perm.check("p1") == FALSE + perm.check("p2") == UNRESOLVED + perm.check("group2") == FALSE + perm.check("p3") == UNRESOLVED when: "Group permission updates" group1.addPermission(repository.getPermission("p2")) then: "Negative permission also updates" - perm.getPermissions().check("p1") == FALSE - perm.getPermissions().check("p2") == FALSE - perm.getPermissions().check("group2") == FALSE - perm.getPermissions().check("p3") == UNRESOLVED + perm.check("p1") == FALSE + perm.check("p2") == FALSE + perm.check("group2") == FALSE + perm.check("p3") == UNRESOLVED when: "Register group2" def group2 = new GroupPermission("group2") @@ -188,15 +153,15 @@ repository.registerPermission(group2) then: "Negative permission also updates" - perm.getPermissions().check("p1") == FALSE - perm.getPermissions().check("p2") == FALSE - perm.getPermissions().check("group2") == UNRESOLVED - perm.getPermissions().check("p3") == TRUE + perm.check("p1") == FALSE + perm.check("p2") == FALSE + perm.check("group2") == UNRESOLVED + perm.check("p3") == TRUE and: "Group1 updates too" - group1.getPermissions().check("p1") == TRUE - group1.getPermissions().check("p2") == TRUE - group1.getPermissions().check("group2") == UNRESOLVED - group1.getPermissions().check("p3") == FALSE + group1.check("p1") == TRUE + group1.check("p2") == TRUE + group1.check("group2") == UNRESOLVED + group1.check("p3") == FALSE } } diff --git a/src/test/groovy/org/ultramine/permission/PermissionResolverTest.groovy b/src/test/groovy/org/ultramine/permission/PermissionResolverTest.groovy index 51f106a..4665fda 100644 --- a/src/test/groovy/org/ultramine/permission/PermissionResolverTest.groovy +++ b/src/test/groovy/org/ultramine/permission/PermissionResolverTest.groovy @@ -1,22 +1,15 @@ package org.ultramine.permission +import org.ultramine.permission.internal.PermissionResolver import spock.lang.Specification import spock.lang.Unroll -import static org.ultramine.permission.PermissionResolver.CheckResult.* +import static org.ultramine.permission.internal.CheckResult.* /** * Created by Евгений on 08.05.2014. */ class PermissionResolverTest extends Specification { - def setupSpec() { - PermissionResolver.metaClass.addEntry = { String key, Boolean value, Integer prio -> - delegate.values.put(key, value) - delegate.priorities.put(key, prio) - return delegate - } - } - @Unroll def "Test createForKey: #key"() { when: "Creating resolver for key" @@ -32,8 +25,8 @@ def "Test createInverted"() { setup: def resolver = new PermissionResolver() - resolver.addEntry("p.true", true, 0) - resolver.addEntry("p.false", false, 0) + resolver.merge("p.true", true, 0) + resolver.merge("p.false", false, 0) when: "Create inverted resolver" def inverted = PermissionResolver.createInverted(resolver) @@ -49,7 +42,7 @@ def "Test wildcard"() { setup: "Resolver with wildcard permission" def resolver = new PermissionResolver() - resolver.addEntry("test.perm.*", true, 0) + resolver.merge("test.perm.*", true, 0) expect: "Other permissions are not affected" resolver.check("group.admin") == UNRESOLVED @@ -67,8 +60,8 @@ def "Test single permission override wildcard"() { setup: "Resolver with wildcard and permission" def resolver = new PermissionResolver() - resolver.addEntry("test.perm.*", true, 1) - resolver.addEntry("test.perm.super", false, 0) + resolver.merge("test.perm.*", true, 1) + resolver.merge("test.perm.super", false, 0) expect: "Wildcard has lower priority" resolver.check("test.perm.super") == FALSE @@ -85,8 +78,8 @@ def "Test higher node wildcard priority"() { setup: "Resolver with wildcards" def resolver = new PermissionResolver() - resolver.addEntry("test.perm.*", true, 1) - resolver.addEntry("test.perm.super.*", false, 0) + resolver.merge("test.perm.*", true, 1) + resolver.merge("test.perm.super.*", false, 0) expect: "Higher node wildcard has priority" resolver.check("test.perm.super.p") == FALSE @@ -105,7 +98,7 @@ def "Test clear"() { setup: def resolver = new PermissionResolver() - resolver.addEntry("test.perm", true, 0) + resolver.merge("test.perm", true, 0) when: "Clear resolver's data" resolver.clear() @@ -117,15 +110,15 @@ def "Test merge"() { setup: "First resolver" def resolver1 = new PermissionResolver() - resolver1.addEntry("test.perm", true, 1) - resolver1.addEntry("test.perm.1", true, 1) - resolver1.addEntry("test.perm.2", false, 1) + resolver1.merge("test.perm", true, 1) + resolver1.merge("test.perm.1", true, 1) + resolver1.merge("test.perm.2", false, 1) and: "Second resolver" def resolver2 = new PermissionResolver() - resolver2.addEntry("test.perm", false, 0) - resolver2.addEntry("test.perm.1", false, 2) - resolver2.addEntry("test.perm.3", true, 2) + resolver2.merge("test.perm", false, 0) + resolver2.merge("test.perm.1", false, 2) + resolver2.merge("test.perm.3", true, 2) when: "Merging first then second" def result = new PermissionResolver() @@ -164,8 +157,10 @@ def "Test clear -> merge lower priority"() { setup: "resolver(^test, 100)" - def resolver = new PermissionResolver().addEntry("test", false, 100) - def inverted = new PermissionResolver().addEntry("test", true, 50) + def resolver = new PermissionResolver() + resolver.merge("test", false, 100) + def inverted = new PermissionResolver() + inverted.merge("test", true, 50) when: resolver.clear() diff --git a/src/test/groovy/org/ultramine/permission/UserContainerTest.groovy b/src/test/groovy/org/ultramine/permission/UserContainerTest.groovy index 743e3e6..10f913f 100644 --- a/src/test/groovy/org/ultramine/permission/UserContainerTest.groovy +++ b/src/test/groovy/org/ultramine/permission/UserContainerTest.groovy @@ -1,16 +1,14 @@ package org.ultramine.permission +import org.ultramine.permission.internal.UserContainer import spock.lang.Specification class UserContainerTest extends Specification { def stubUser(String name, Map permissions) { - def resolver = new PermissionResolver(); - resolver.merge(permissions, 0) - Mock(User) { - getName() >> name - getPermissions() >> resolver - } + def user = new User(name) + user.permissionResolver.merge(permissions, 0) + return user } def "Test permissions"() { diff --git a/src/test/groovy/org/ultramine/permission/WorldTest.groovy b/src/test/groovy/org/ultramine/permission/WorldTest.groovy index 776ad45..2da0c66 100644 --- a/src/test/groovy/org/ultramine/permission/WorldTest.groovy +++ b/src/test/groovy/org/ultramine/permission/WorldTest.groovy @@ -6,8 +6,8 @@ def "Test config parsing"() { setup: - def container = new World(new PermissionRepository()) - container.load(testWorldData) + def container = new World() + container.load(new PermissionRepository(), testWorldData) expect: "Permissions are loaded correctly" container.checkUserPermission("user1", "d") @@ -23,18 +23,18 @@ !container.checkUserPermission("user2", "group.admin") and: "Meta is loaded correctly" - container.get("user1").getMeta().getString("a") == "a" - container.get("user1").getMeta().getInt("b") == 1 + container.get("user1").getMeta("a") == "a" + container.get("user1").getMeta("b") == "1" - !container.get("user2").getMeta().getString("a") - !container.get("user2").getMeta().getInt("b") + !container.get("user2").getMeta("a") + !container.get("user2").getMeta("b") } def "Test config reloading"() { setup: def repository = new PermissionRepository() - def container = new World(repository) - container.load(testWorldData) + def container = new World() + container.load(repository, testWorldData) when: "Add permission and meta to user" container.get("user1").addPermission(repository.getPermission("test")) @@ -42,14 +42,14 @@ then: "User have this permission and meta" container.checkUserPermission("user1", "test") - container.get("user2").getMeta().getString("test") == "data" + container.get("user2").getMeta("test") == "data" when: "Reloading container" - container.load(testWorldData) + container.load(repository, testWorldData) then: "User have not this permission and meta" !container.checkUserPermission("user1", "test") - !container.get("user2").getMeta().getString("test") + !container.get("user2").getMeta("test") and: "Container is reloaded correctly" container.checkUserPermission("user1", "d") @@ -64,16 +64,16 @@ container.checkUserPermission("user2", "p.3") !container.checkUserPermission("user2", "group.admin") - container.get("user1").getMeta().getString("a") == "a" - container.get("user1").getMeta().getInt("b") == 1 - !container.get("user2").getMeta().getString("a") - !container.get("user2").getMeta().getInt("b") + container.get("user1").getMeta("a") == "a" + container.get("user1").getMeta("b") == "1" + !container.get("user2").getMeta("a") + !container.get("user2").getMeta("b") } def "Test config saving"() { setup: def repository = new PermissionRepository() - def container = new World(repository) + def container = new World() def user = new User("test") user.addPermission(repository.getPermission("p1")) user.addPermission(repository.getPermission("^p2")) @@ -94,8 +94,8 @@ data.users['test'].meta.size() == 0 when: "Try to load this config" - def anotherContainer = new World(repository) - anotherContainer.load(data) + def anotherContainer = new World() + anotherContainer.load(repository, data) then: "Container loaded correctly" anotherContainer.checkUserPermission("test", "d1") @@ -113,7 +113,7 @@ users: [ user1: new World.HolderData( permissions: ['p.1', '^p.2'], - meta: [a: 'a', b: 1] + meta: [a: 'a', b: "1"] ), user2: new World.HolderData( permissions: ['^d', 'p.3'],