Pregen config & cmd perm fixes

Added perm group check
Needs testing
This commit is contained in:
Norbi Peti 2019-05-01 00:41:31 +02:00
parent 4dade43f82
commit 0d4f3b09dd
No known key found for this signature in database
GPG key ID: DBA4C4549A927E56
4 changed files with 73 additions and 20 deletions

View file

@ -9,6 +9,11 @@ import lombok.Getter;
import lombok.experimental.var;
import org.bukkit.plugin.java.JavaPlugin;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Optional;
import java.util.Stack;
@HasConfig
@ -42,12 +47,13 @@ public abstract class ButtonPlugin extends JavaPlugin {
@Override
public final void onEnable() {
loadConfig();
IHaveConfig.pregenConfig(this, null);
try {
pluginEnable();
} catch (Exception e) {
TBMCCoreAPI.SendException("Error while enabling plugin " + getName() + "!", e);
}
if (configGenAllowed(this)) //If it's not disabled (by default it's not)
IHaveConfig.pregenConfig(this, null);
}
private void loadConfig() {
@ -91,4 +97,15 @@ public abstract class ButtonPlugin extends JavaPlugin {
loaded = true; //Needed because for the first time it uses reloadConfig() to load it
return true;
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ConfigOpts {
boolean disableConfigGen() default false;
}
public static boolean configGenAllowed(Object obj) {
return !Optional.ofNullable(obj.getClass().getAnnotation(ConfigOpts.class))
.map(ConfigOpts::disableConfigGen).orElse(false);
}
}

View file

@ -45,7 +45,7 @@ public abstract class Component<TP extends JavaPlugin> {
* Registers a component checking it's dependencies and calling {@link #register(JavaPlugin)}.<br>
* Make sure to register the dependencies first.<br>
* The component will be enabled automatically, regardless of when it was registered.<br>
* <b>If not using {@link ButtonPlugin}, call {@link ComponentManager#unregComponents(ButtonPlugin)} on plugin disable.</b>
* <b>If not using {@link ButtonPlugin}, call {@link ComponentManager#unregComponents(ButtonPlugin)} on plugin disable.</b>
*
* @param component The component to register
* @return Whether the component is registered successfully (it may have failed to enable)
@ -57,7 +57,7 @@ public abstract class Component<TP extends JavaPlugin> {
/**
* Unregisters a component by calling {@link #unregister(JavaPlugin)}.<br>
* Make sure to unregister the dependencies last.<br>
* <b>Components will be unregistered in opposite order of registering by default by {@link ButtonPlugin} or {@link ComponentManager#unregComponents(ButtonPlugin)}.</b>
* <b>Components will be unregistered in opposite order of registering by default by {@link ButtonPlugin} or {@link ComponentManager#unregComponents(ButtonPlugin)}.</b>
*
* @param component The component to unregister
* @return Whether the component is unregistered successfully (it also got disabled)
@ -85,7 +85,6 @@ public abstract class Component<TP extends JavaPlugin> {
}
component.plugin = plugin;
updateConfig(plugin, component);
IHaveConfig.pregenConfig(component, null);
component.register(plugin);
components.put(component.getClass(), component);
if (plugin instanceof ButtonPlugin)
@ -134,6 +133,8 @@ public abstract class Component<TP extends JavaPlugin> {
if (component.enabled = enabled) {
updateConfig(component.getPlugin(), component);
component.enable();
if (ButtonPlugin.configGenAllowed(component))
IHaveConfig.pregenConfig(component, null);
} else {
component.disable();
component.plugin.saveConfig();
@ -193,7 +194,7 @@ public abstract class Component<TP extends JavaPlugin> {
/**
* Disables the module, when called by the JavaPlugin class. Do
* any cleanups needed within this method.
* To access the plugin, use {@link #getPlugin()}.
* To access the plugin, use {@link #getPlugin()}.
*/
protected abstract void disable();
@ -229,14 +230,15 @@ public abstract class Component<TP extends JavaPlugin> {
/**
* Returns a map of configs that are under the given key.
* @param key The key to use
*
* @param key The key to use
* @param defaultProvider A mapping between config paths and config generators
* @return A map containing configs
*/
protected Map<String, IHaveConfig> getConfigMap(String key, Map<String, Consumer<IHaveConfig>> defaultProvider) {
val c=getConfig().getConfig();
var cs=c.getConfigurationSection(key);
if(cs==null) cs=c.createSection(key);
val c = getConfig().getConfig();
var cs = c.getConfigurationSection(key);
if (cs == null) cs = c.createSection(key);
val res = cs.getValues(false).entrySet().stream().filter(e -> e.getValue() instanceof ConfigurationSection)
.collect(Collectors.toMap(Map.Entry::getKey, kv -> new IHaveConfig((ConfigurationSection) kv.getValue(), getPlugin()::saveConfig)));
if (res.size() == 0) {

View file

@ -105,7 +105,7 @@ public abstract class Command2<TC extends ICommand2, TP extends Command2Sender>
sender.sendMessage(sd.helpText);
return true;
}
if (!hasPermission(sender, sd.command)) {
if (!hasPermission(sender, sd.command, sd.method)) {
sender.sendMessage("§cYou don't have permission to use this command");
return true;
}
@ -283,7 +283,7 @@ public abstract class Command2<TC extends ICommand2, TP extends Command2Sender>
return ht;
}
public abstract boolean hasPermission(TP sender, TC command);
public abstract boolean hasPermission(TP sender, TC command, Method subcommand);
public String[] getCommandsText() {
return commandHelp.toArray(new String[0]);

View file

@ -6,21 +6,27 @@ import org.bukkit.Bukkit;
import org.bukkit.permissions.Permission;
import org.bukkit.permissions.PermissionDefault;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.function.Function;
public class Command2MC extends Command2<ICommand2MC, Command2MCSender> {
@Override
public void registerCommand(ICommand2MC command) {
super.registerCommand(command, '/');
Bukkit.getPluginManager().addPermission(new Permission("thorpe.command." + command.getCommandPath().replace(' ', '.'),
modOnly(command) ? PermissionDefault.OP : PermissionDefault.TRUE)); //Allow commands by default, unless it's mod only - TODO: Test
val perm = "thorpe.command." + command.getCommandPath().replace(' ', '.');
if (Bukkit.getPluginManager().getPermission(perm) == null) //Check needed for plugin reset
Bukkit.getPluginManager().addPermission(new Permission(perm,
modOnly(command) ? PermissionDefault.OP : PermissionDefault.TRUE)); //Allow commands by default, unless it's mod only - TODO: Test
}
@Override
public boolean hasPermission(Command2MCSender sender, ICommand2MC command) {
public boolean hasPermission(Command2MCSender sender, ICommand2MC command, Method method) {
String pg;
return modOnly(command)
? MainPlugin.permission.has(sender.getSender(), "tbmc.admin") //TODO: Change when groups are implemented
//: MainPlugin.permission.has(sender.getSender(), permGroup()) - TODO: Check for subcommands (permGroup)
? MainPlugin.permission.has(sender.getSender(), "tbmc.admin")
: (pg = permGroup(command, method)) != null
? MainPlugin.permission.has(sender.getSender(), pg)
: MainPlugin.permission.has(sender.getSender(), "thorpe.command." + command.getCommandPath().replace(' ', '.'));
}
@ -31,11 +37,39 @@ public class Command2MC extends Command2<ICommand2MC, Command2MCSender> {
* @return Whether the command is mod only
*/
private boolean modOnly(ICommand2MC command) {
for (Class<?> cl = command.getClass(); cl != null; cl = cl.getSuperclass()) {
val cc = command.getClass().getAnnotation(CommandClass.class);
if (cc != null && cc.modOnly()) return true;
return getAnnForValue(command.getClass(), CommandClass.class, CommandClass::modOnly, false);
}
/**
* Returns true if this class or <u>any</u> of the superclasses are mod only.
*
* @param method The subcommand to check
* @return The permission group for the subcommand or null
*/
private String permGroup(ICommand2MC command, Method method) {
val sc = method.getAnnotation(Subcommand.class);
if (sc != null && sc.permGroup().length() > 0) return sc.permGroup();
return getAnnForValue(command.getClass(), CommandClass.class, CommandClass::permGroup, null);
}
/**
* Loops until it finds a value that is <b>not</b> the same as def
*
* @param sourceCl The class which has the annotation
* @param annCl The annotation to get
* @param annMethod The annotation method to check
* @param def The value to ignore when looking for the result
* @param <T> The annotation type
* @param <V> The type of the value
* @return The value returned by the first superclass or def
*/
private <T extends Annotation, V> V getAnnForValue(Class<?> sourceCl, Class<T> annCl, Function<T, V> annMethod, V def) {
for (Class<?> cl = sourceCl; cl != null; cl = cl.getSuperclass()) {
val cc = cl.getAnnotation(annCl);
V r;
if (cc != null && (r = annMethod.apply(cc)) != def) return r;
}
return false;
return def;
}
/**