mirror of
https://github.com/BentoBoxWorld/BentoBox.git
synced 2024-11-23 19:25:12 +01:00
Implements placeholder permissions for addons (#1305)
Implements #1303. Addons will no longer need to see their permissions updated each time there is a new gamemode. They can use [gamemode] in their permissions to automatically register the permissions on all available gamemodes.
This commit is contained in:
parent
fe58159db3
commit
1f3a79127a
@ -8,15 +8,12 @@ import java.net.URLClassLoader;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.permissions.PermissionDefault;
|
||||
import org.bukkit.plugin.InvalidDescriptionException;
|
||||
import org.bukkit.util.permissions.DefaultPermissions;
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
@ -31,7 +28,6 @@ import world.bentobox.bentobox.managers.AddonsManager;
|
||||
*/
|
||||
public class AddonClassLoader extends URLClassLoader {
|
||||
|
||||
private static final String DEFAULT = ".default";
|
||||
private final Map<String, Class<?>> classes = new HashMap<>();
|
||||
private Addon addon;
|
||||
private AddonsManager loader;
|
||||
@ -70,31 +66,16 @@ public class AddonClassLoader extends URLClassLoader {
|
||||
|
||||
addon = addonClass.getDeclaredConstructor().newInstance();
|
||||
addon.setDescription(asDescription(data));
|
||||
// Set permissions
|
||||
if (data.isConfigurationSection("permissions")) {
|
||||
ConfigurationSection perms = data.getConfigurationSection("permissions");
|
||||
perms.getKeys(true).forEach(perm -> {
|
||||
if (perms.contains(perm + DEFAULT) && perms.contains(perm + ".description")) {
|
||||
registerPermission(perms, perm);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void registerPermission(ConfigurationSection perms, String perm) {
|
||||
if (perms.getString(perm + DEFAULT) == null) {
|
||||
Bukkit.getLogger().severe("Permission default is invalid : " + perms.getName());
|
||||
return;
|
||||
}
|
||||
PermissionDefault pd = PermissionDefault.getByName(perms.getString(perm + DEFAULT));
|
||||
if (pd == null) {
|
||||
Bukkit.getLogger().severe("Permission default is invalid : " + perms.getName());
|
||||
return;
|
||||
}
|
||||
String desc = perms.getString(perm + ".description");
|
||||
DefaultPermissions.registerPermission(perm, desc, pd);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convers the addon.yml to an AddonDescription
|
||||
* @param data - yaml config (addon.yml)
|
||||
* @return Addon Description
|
||||
* @throws InvalidAddonDescriptionException - if there's a bug in the addon.yml
|
||||
*/
|
||||
@NonNull
|
||||
private AddonDescription asDescription(YamlConfiguration data) throws InvalidAddonDescriptionException {
|
||||
AddonDescription.Builder builder = new AddonDescription.Builder(data.getString("main"), data.getString("name"), data.getString("version"))
|
||||
@ -119,6 +100,10 @@ public class AddonClassLoader extends URLClassLoader {
|
||||
}
|
||||
builder.apiVersion(apiVersion);
|
||||
}
|
||||
// Set permissions
|
||||
if (data.isConfigurationSection("permissions")) {
|
||||
builder.permissions(Objects.requireNonNull(data.getConfigurationSection("permissions")));
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
@ -5,7 +5,9 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* @author tastybento, Poslovitch
|
||||
@ -19,6 +21,7 @@ public final class AddonDescription {
|
||||
private final @NonNull List<String> authors;
|
||||
private final @NonNull List<String> dependencies;
|
||||
private final @NonNull List<String> softDependencies;
|
||||
private final @Nullable ConfigurationSection permissions;
|
||||
/**
|
||||
* Whether the addon should be included in Metrics or not.
|
||||
* @since 1.1
|
||||
@ -54,6 +57,7 @@ public final class AddonDescription {
|
||||
this.repository = builder.repository;
|
||||
this.icon = builder.icon;
|
||||
this.apiVersion = builder.apiVersion;
|
||||
this.permissions = builder.permissions;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@ -150,6 +154,14 @@ public final class AddonDescription {
|
||||
return apiVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the permissions
|
||||
* @since 1.13.0
|
||||
*/
|
||||
public ConfigurationSection getPermissions() {
|
||||
return permissions;
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private @NonNull String main;
|
||||
private @NonNull String name;
|
||||
@ -162,6 +174,7 @@ public final class AddonDescription {
|
||||
private @NonNull String repository = "";
|
||||
private @NonNull Material icon = Material.PAPER;
|
||||
private @NonNull String apiVersion = "1";
|
||||
private @Nullable ConfigurationSection permissions;
|
||||
|
||||
/**
|
||||
* @since 1.1
|
||||
@ -243,5 +256,17 @@ public final class AddonDescription {
|
||||
public AddonDescription build() {
|
||||
return new AddonDescription(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the permission config section. Taken from the addon.yml
|
||||
* @param permissions - YAML configuration section
|
||||
* @return Builder
|
||||
* @since 1.13.0
|
||||
*/
|
||||
@NonNull
|
||||
public Builder permissions(ConfigurationSection permissions) {
|
||||
this.permissions = permissions;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,11 +21,14 @@ import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.bukkit.permissions.PermissionDefault;
|
||||
import org.bukkit.util.permissions.DefaultPermissions;
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
@ -34,6 +37,7 @@ import world.bentobox.bentobox.api.addons.Addon;
|
||||
import world.bentobox.bentobox.api.addons.Addon.State;
|
||||
import world.bentobox.bentobox.api.addons.AddonClassLoader;
|
||||
import world.bentobox.bentobox.api.addons.GameModeAddon;
|
||||
import world.bentobox.bentobox.api.addons.exceptions.InvalidAddonDescriptionException;
|
||||
import world.bentobox.bentobox.api.addons.exceptions.InvalidAddonFormatException;
|
||||
import world.bentobox.bentobox.api.configuration.ConfigObject;
|
||||
import world.bentobox.bentobox.api.events.addon.AddonEvent;
|
||||
@ -46,6 +50,10 @@ import world.bentobox.bentobox.util.Util;
|
||||
*/
|
||||
public class AddonsManager {
|
||||
|
||||
private static final String DEFAULT = ".default";
|
||||
|
||||
private static final String GAMEMODE = "[gamemode].";
|
||||
|
||||
@NonNull
|
||||
private List<Addon> addons;
|
||||
@NonNull
|
||||
@ -154,10 +162,42 @@ public class AddonsManager {
|
||||
* Enables all the addons
|
||||
*/
|
||||
public void enableAddons() {
|
||||
if (!getLoadedAddons().isEmpty()) {
|
||||
plugin.log("Enabling addons...");
|
||||
getLoadedAddons().forEach(this::enableAddon);
|
||||
plugin.log("Addons successfully enabled.");
|
||||
if (getLoadedAddons().isEmpty()) return;
|
||||
plugin.log("Enabling addons...");
|
||||
getLoadedAddons().forEach(this::enableAddon);
|
||||
// Set perms for enabled addons
|
||||
this.getEnabledAddons().forEach(this::setPerms);
|
||||
plugin.log("Addons successfully enabled.");
|
||||
}
|
||||
|
||||
void setPerms(Addon addon) {
|
||||
ConfigurationSection perms = addon.getDescription().getPermissions();
|
||||
perms.getKeys(true).parallelStream().filter(perm -> perms.contains(perm + DEFAULT) && perms.contains(perm + ".description"))
|
||||
.forEach(perm -> {
|
||||
try {
|
||||
registerPermission(perms, perm);
|
||||
} catch (InvalidAddonDescriptionException e) {
|
||||
plugin.logError("Addon " + addon.getDescription().getName() + ": " + e.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void registerPermission(ConfigurationSection perms, String perm) throws InvalidAddonDescriptionException {
|
||||
if (perms.getString(perm + DEFAULT) == null) {
|
||||
throw new InvalidAddonDescriptionException("Permission default is invalid : " + perm + DEFAULT);
|
||||
}
|
||||
PermissionDefault pd = PermissionDefault.getByName(perms.getString(perm + DEFAULT));
|
||||
if (pd == null) {
|
||||
throw new InvalidAddonDescriptionException("Permission default is invalid : " + perm + DEFAULT);
|
||||
}
|
||||
String desc = perms.getString(perm + ".description");
|
||||
// Replace placeholders for Game Mode Addon names
|
||||
if (perm.contains(GAMEMODE)) {
|
||||
getGameModeAddons().stream().map(g -> g.getPermissionPrefix())
|
||||
.forEach(p -> DefaultPermissions.registerPermission(perm.replace(GAMEMODE, p), desc, pd));
|
||||
} else {
|
||||
// Single perm
|
||||
DefaultPermissions.registerPermission(perm, desc, pd);
|
||||
}
|
||||
}
|
||||
|
||||
@ -380,6 +420,9 @@ public class AddonsManager {
|
||||
classes.putIfAbsent(name, clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the addons into loading order taking into account dependencies
|
||||
*/
|
||||
private void sortAddons() {
|
||||
// Lists all available addons as names.
|
||||
List<String> names = addons.stream().map(a -> a.getDescription().getName()).collect(Collectors.toList());
|
||||
|
@ -5,6 +5,9 @@ import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
@ -14,9 +17,15 @@ import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.bukkit.permissions.PermissionDefault;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.util.permissions.DefaultPermissions;
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@ -31,12 +40,16 @@ import org.powermock.reflect.Whitebox;
|
||||
import world.bentobox.bentobox.BentoBox;
|
||||
import world.bentobox.bentobox.Settings;
|
||||
import world.bentobox.bentobox.api.addons.Addon;
|
||||
import world.bentobox.bentobox.api.addons.Addon.State;
|
||||
import world.bentobox.bentobox.api.addons.AddonDescription;
|
||||
import world.bentobox.bentobox.api.addons.GameModeAddon;
|
||||
import world.bentobox.bentobox.api.addons.exceptions.InvalidAddonDescriptionException;
|
||||
import world.bentobox.bentobox.api.configuration.WorldSettings;
|
||||
import world.bentobox.bentobox.database.DatabaseSetup.DatabaseType;
|
||||
import world.bentobox.bentobox.database.objects.DataObject;
|
||||
|
||||
@RunWith(PowerMockRunner.class)
|
||||
@PrepareForTest( {Bukkit.class, BentoBox.class} )
|
||||
@PrepareForTest( {Bukkit.class, BentoBox.class, DefaultPermissions.class} )
|
||||
public class AddonsManagerTest {
|
||||
|
||||
private BentoBox plugin;
|
||||
@ -67,6 +80,8 @@ public class AddonsManagerTest {
|
||||
when(s.getDatabaseType()).thenReturn(DatabaseType.MYSQL);
|
||||
// settings
|
||||
when(plugin.getSettings()).thenReturn(s);
|
||||
|
||||
PowerMockito.mockStatic(DefaultPermissions.class);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -335,5 +350,78 @@ public class AddonsManagerTest {
|
||||
assertFalse(am.isAddonCompatibleWithBentoBox(addon, "1.11.1"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link world.bentobox.bentobox.managers.AddonsManager#registerPermission(org.bukkit.configuration.ConfigurationSection, String)}
|
||||
* @throws InvalidAddonDescriptionException
|
||||
* @throws InvalidConfigurationException
|
||||
*/
|
||||
@Test
|
||||
public void testRegisterPermissionStandardPerm() throws InvalidAddonDescriptionException, InvalidConfigurationException {
|
||||
String perms =
|
||||
" 'bskyblock.intopten':\n" +
|
||||
" description: Player is in the top ten.\n" +
|
||||
" default: true\n";
|
||||
YamlConfiguration config = new YamlConfiguration();
|
||||
config.loadFromString(perms);
|
||||
am.registerPermission(config, "bskyblock.intopten");
|
||||
PowerMockito.verifyStatic(DefaultPermissions.class);
|
||||
DefaultPermissions.registerPermission(eq("bskyblock.intopten"), anyString(), any(PermissionDefault.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link world.bentobox.bentobox.managers.AddonsManager#registerPermission(org.bukkit.configuration.ConfigurationSection, String)}
|
||||
* @throws InvalidAddonDescriptionException
|
||||
* @throws InvalidConfigurationException
|
||||
*/
|
||||
@Test
|
||||
public void testRegisterPermissionGameModePerm() throws InvalidAddonDescriptionException, InvalidConfigurationException {
|
||||
String perms =
|
||||
" '[gamemode].intopten':\n" +
|
||||
" description: Player is in the top ten.\n" +
|
||||
" default: true\n";
|
||||
YamlConfiguration config = new YamlConfiguration();
|
||||
config.loadFromString(perms);
|
||||
GameModeAddon addon = new MyGameMode();
|
||||
AddonDescription addonDesc = new AddonDescription.Builder("main.class", "mygame", "1.0.0").apiVersion("1.11.1.0.0.0.1")
|
||||
.permissions(config)
|
||||
.build();
|
||||
addon.setDescription(addonDesc);
|
||||
addon.setState(State.ENABLED);
|
||||
am.getAddons().add(addon);
|
||||
am.registerPermission(config, "[gamemode].intopten");
|
||||
PowerMockito.verifyStatic(DefaultPermissions.class);
|
||||
DefaultPermissions.registerPermission(eq("mygame.intopten"), anyString(), any(PermissionDefault.class));
|
||||
}
|
||||
|
||||
|
||||
|
||||
class MyGameMode extends GameModeAddon {
|
||||
|
||||
@Override
|
||||
public void createWorlds() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldSettings getWorldSettings() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ChunkGenerator getDefaultWorldGenerator(String worldName, String id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveWorldSettings() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user