diff --git a/common/src/main/java/me/lucko/luckperms/common/commands/impl/generic/other/HolderEditor.java b/common/src/main/java/me/lucko/luckperms/common/commands/impl/generic/other/HolderEditor.java index f1cdaa085..ce6be9d55 100644 --- a/common/src/main/java/me/lucko/luckperms/common/commands/impl/generic/other/HolderEditor.java +++ b/common/src/main/java/me/lucko/luckperms/common/commands/impl/generic/other/HolderEditor.java @@ -36,10 +36,10 @@ import me.lucko.luckperms.common.commands.CommandException; import me.lucko.luckperms.common.commands.CommandResult; import me.lucko.luckperms.common.commands.abstraction.SubCommand; import me.lucko.luckperms.common.commands.sender.Sender; +import me.lucko.luckperms.common.config.ConfigKeys; import me.lucko.luckperms.common.constants.Message; import me.lucko.luckperms.common.constants.Permission; import me.lucko.luckperms.common.core.NodeModel; -import me.lucko.luckperms.common.core.PriorityComparator; import me.lucko.luckperms.common.core.model.Group; import me.lucko.luckperms.common.core.model.PermissionHolder; import me.lucko.luckperms.common.core.model.User; @@ -56,13 +56,16 @@ import java.io.StringWriter; import java.net.HttpURLConnection; import java.net.URL; import java.nio.charset.StandardCharsets; -import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import java.util.stream.Collectors; public class HolderEditor extends SubCommand { + private static final String USER_ID_PATTERN = "user/"; + private static final String GROUP_ID_PATTERN = "group/"; + private static final String FILE_NAME = "luckperms-data.json"; + public HolderEditor(boolean user) { super("editor", "Opens the web permission editor", user ? Permission.USER_EDITOR : Permission.GROUP_EDITOR, Predicates.alwaysFalse(), null @@ -83,8 +86,8 @@ public class HolderEditor extends SubCommand { } List parts = Splitter.on('/').splitToList(dataUrl); - String id = parts.get(4) + "/" + parts.get(6); - String url = "https://lpedit.lucko.me/?" + id; + String id = "?" + parts.get(4) + "/" + parts.get(6); + String url = plugin.getConfiguration().get(ConfigKeys.WEB_EDITOR_URL_PATTERN) + id; Message.EDITOR_URL.send(sender); sender.sendMessage(new FancyMessage(url).color(ChatColor.getByChar('b')).link(url)); @@ -94,10 +97,10 @@ public class HolderEditor extends SubCommand { private static String id(PermissionHolder holder) { if (holder instanceof User) { User user = ((User) holder); - return "user/" + user.getUuid().toString(); + return USER_ID_PATTERN + user.getUuid().toString(); } else { Group group = ((Group) holder); - return "group/" + group.getName(); + return GROUP_ID_PATTERN + group.getName(); } } @@ -115,7 +118,7 @@ public class HolderEditor extends SubCommand { .name("description").value("LuckPerms Web Permissions Editor Data") .name("public").value(false) .name("files") - .beginObject().name("luckperms-data.json") + .beginObject().name(FILE_NAME) .beginObject().name("content").value(content) .endObject() .endObject() @@ -131,7 +134,7 @@ public class HolderEditor extends SubCommand { try (InputStream inputStream = connection.getInputStream()) { try (InputStreamReader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) { JsonObject response = new Gson().fromJson(reader, JsonObject.class); - return response.get("files").getAsJsonObject().get("luckperms-data.json").getAsJsonObject().get("raw_url").getAsString(); + return response.get("files").getAsJsonObject().get(FILE_NAME).getAsJsonObject().get("raw_url").getAsString(); } } @@ -150,7 +153,7 @@ public class HolderEditor extends SubCommand { } private static JsonArray serializePermissions(Set nodes) { - List data = new ArrayList<>(); + JsonArray arr = new JsonArray(); for (NodeModel node : nodes) { JsonObject attributes = new JsonObject(); @@ -173,17 +176,7 @@ public class HolderEditor extends SubCommand { attributes.add("context", node.getContextsAsJson()); } - data.add(attributes); - } - - data.sort((o1, o2) -> PriorityComparator.get().compareStrings( - o1.get("permission").getAsString(), - o2.get("permission").getAsString() - )); - - JsonArray arr = new JsonArray(); - for (JsonObject o : data) { - arr.add(o); + arr.add(attributes); } return arr; diff --git a/common/src/main/java/me/lucko/luckperms/common/config/ConfigKeys.java b/common/src/main/java/me/lucko/luckperms/common/config/ConfigKeys.java index f46fa92de..8b71440b9 100644 --- a/common/src/main/java/me/lucko/luckperms/common/config/ConfigKeys.java +++ b/common/src/main/java/me/lucko/luckperms/common/config/ConfigKeys.java @@ -57,21 +57,67 @@ import java.util.List; import java.util.Map; import java.util.function.Function; +/** + * A class of static {@link ConfigKey}s used by the plugin. + */ @UtilityClass public class ConfigKeys { + /** + * The name of the server + */ public static final ConfigKey SERVER = LowercaseStringKey.of("server", "global"); + + /** + * How many minutes to wait between syncs. A value <= 0 will disable syncing. + */ public static final ConfigKey SYNC_TIME = EnduringKey.wrap(IntegerKey.of("data.sync-minutes", -1)); - public static final ConfigKey DEFAULT_GROUP_NODE = StaticKey.of("group.default"); // constant since 2.6 - public static final ConfigKey DEFAULT_GROUP_NAME = StaticKey.of("default"); // constant since 2.6 + + /** + * The permission node associated with the default group + * + * Constant since 2.6 + */ + public static final ConfigKey DEFAULT_GROUP_NODE = StaticKey.of("group.default"); + + /** + * The name of the default group + * + * Constant since 2.6 + */ + public static final ConfigKey DEFAULT_GROUP_NAME = StaticKey.of("default"); + + /** + * If permissions without a server context should be included. + */ public static final ConfigKey INCLUDING_GLOBAL_PERMS = BooleanKey.of("include-global", true); + + /** + * If permissions without a world context should be included. + */ public static final ConfigKey INCLUDING_GLOBAL_WORLD_PERMS = BooleanKey.of("include-global-world", true); + + /** + * If groups without a server context should be included. + */ public static final ConfigKey APPLYING_GLOBAL_GROUPS = BooleanKey.of("apply-global-groups", true); + + /** + * If groups without a world context should be included. + */ public static final ConfigKey APPLYING_GLOBAL_WORLD_GROUPS = BooleanKey.of("apply-global-world-groups", true); + + /** + * If the server provided uuids should be used. False if we should use the LP cache for existing users. + */ public static final ConfigKey USE_SERVER_UUIDS = AbstractKey.of(c -> { // backwards compatible with the old online-mode option return c.contains("use-server-uuids") ? c.getBoolean("use-server-uuids", true) : c.getBoolean("online-mode", true); }); + + /** + * Controls how temporary add commands should behave + */ public static final ConfigKey TEMPORARY_ADD_BEHAVIOUR = AbstractKey.of(c -> { String option = c.getString("temporary-add-behaviour", "deny").toLowerCase(); if (!option.equals("deny") && !option.equals("replace") && !option.equals("accumulate")) { @@ -80,6 +126,10 @@ public class ConfigKeys { return TemporaryModifier.valueOf(option.toUpperCase()); }); + + /** + * How primary groups should be calculated. + */ public static final ConfigKey PRIMARY_GROUP_CALCULATION_METHOD = EnduringKey.wrap(AbstractKey.of(c -> { String option = c.getString("primary-group-calculation", "stored").toLowerCase(); if (!option.equals("stored") && !option.equals("parents-by-weight") && !option.equals("all-parents-by-weight")) { @@ -88,6 +138,10 @@ public class ConfigKeys { return option; })); + + /** + * A function to create primary group holder instances based upon the {@link #PRIMARY_GROUP_CALCULATION_METHOD} setting. + */ public static final ConfigKey> PRIMARY_GROUP_CALCULATION = EnduringKey.wrap(AbstractKey.of(c -> { String option = PRIMARY_GROUP_CALCULATION_METHOD.get(c); switch (option) { @@ -99,15 +153,55 @@ public class ConfigKeys { return (Function) AllParentsByWeightHolder::new; } })); + + /** + * If wildcards are being applied + */ public static final ConfigKey APPLYING_WILDCARDS = EnduringKey.wrap(BooleanKey.of("apply-wildcards", true)); + + /** + * If regex permissions are being applied + */ public static final ConfigKey APPLYING_REGEX = EnduringKey.wrap(BooleanKey.of("apply-regex", true)); + + /** + * If shorthand permissions are being applied + */ public static final ConfigKey APPLYING_SHORTHAND = EnduringKey.wrap(BooleanKey.of("apply-shorthand", true)); + + /** + * If Bukkit child permissions are being applied. This setting is ignored on other platforms. + */ public static final ConfigKey APPLY_BUKKIT_CHILD_PERMISSIONS = EnduringKey.wrap(BooleanKey.of("apply-bukkit-child-permissions", true)); + + /** + * If Bukkit default permissions are being applied. This setting is ignored on other platforms. + */ public static final ConfigKey APPLY_BUKKIT_DEFAULT_PERMISSIONS = EnduringKey.wrap(BooleanKey.of("apply-bukkit-default-permissions", true)); + + /** + * If Bukkit attachment permissions are being applied. This setting is ignored on other platforms. + */ public static final ConfigKey APPLY_BUKKIT_ATTACHMENT_PERMISSIONS = EnduringKey.wrap(BooleanKey.of("apply-bukkit-attachment-permissions", true)); + + /** + * If BungeeCord configured permissions are being applied. This setting is ignored on other platforms. + */ public static final ConfigKey APPLY_BUNGEE_CONFIG_PERMISSIONS = EnduringKey.wrap(BooleanKey.of("apply-bungee-config-permissions", false)); + + /** + * If Sponge's implicit permission inheritance system should be applied + */ public static final ConfigKey APPLY_SPONGE_IMPLICIT_WILDCARDS = EnduringKey.wrap(BooleanKey.of("apply-sponge-implicit-wildcards", true)); + + /** + * If Sponge default subjects should be applied + */ public static final ConfigKey APPLY_SPONGE_DEFAULT_SUBJECTS = EnduringKey.wrap(BooleanKey.of("apply-sponge-default-subjects", true)); + + /** + * The configured group weightings + */ public static final ConfigKey> GROUP_WEIGHTS = AbstractKey.of(c -> { return c.getMap("group-weight", ImmutableMap.of()).entrySet().stream().collect(ImmutableCollectors.toImmutableMap( e -> e.getKey().toLowerCase(), @@ -120,6 +214,10 @@ public class ConfigKeys { }) ); }); + + /** + * Creates a new prefix MetaStack element based upon the configured values. Be aware that this instance should be copied for each unique user. + */ public static final ConfigKey PREFIX_FORMATTING_OPTIONS = AbstractKey.of(l -> { List format = l.getList("meta-formatting.prefix.format", new ArrayList<>()); if (format.isEmpty()) { @@ -131,6 +229,10 @@ public class ConfigKeys { return new GenericMetaStack(StackElementFactory.fromList(l.getPlugin(), format, true), startSpacer, middleSpacer, endSpacer); }); + + /** + * Creates a new suffix MetaStack element based upon the configured values. Be aware that this instance should be copied for each unique user. + */ public static final ConfigKey SUFFIX_FORMATTING_OPTIONS = AbstractKey.of(l -> { List format = l.getList("meta-formatting.suffix.format", new ArrayList<>()); if (format.isEmpty()) { @@ -142,10 +244,30 @@ public class ConfigKeys { return new GenericMetaStack(StackElementFactory.fromList(l.getPlugin(), format, false), startSpacer, middleSpacer, endSpacer); }); + + /** + * If log notifications are enabled + */ public static final ConfigKey LOG_NOTIFY = BooleanKey.of("log-notify", true); + + /** + * If auto op is enabled. Only used by the Bukkit platform. + */ public static final ConfigKey AUTO_OP = EnduringKey.wrap(BooleanKey.of("auto-op", false)); + + /** + * If server operators should be enabled. Only used by the Bukkit platform. + */ public static final ConfigKey OPS_ENABLED = EnduringKey.wrap(AbstractKey.of(c -> !AUTO_OP.get(c) && c.getBoolean("enable-ops", true))); + + /** + * If server operators should be able to use LuckPerms commands by default. Only used by the Bukkit platform. + */ public static final ConfigKey COMMANDS_ALLOW_OP = EnduringKey.wrap(BooleanKey.of("commands-allow-op", true)); + + /** + * The name of the server to use for Vault. + */ public static final ConfigKey VAULT_SERVER = AbstractKey.of(c -> { // default to true for backwards compatibility if (c.getBoolean("use-vault-server", true)) { @@ -154,15 +276,41 @@ public class ConfigKeys { return SERVER.get(c); } }); + + /** + * If Vault should apply global permissions + */ public static final ConfigKey VAULT_INCLUDING_GLOBAL = BooleanKey.of("vault-include-global", true); + + /** + * If any worlds provided with Vault lookups should be ignored + */ public static final ConfigKey VAULT_IGNORE_WORLD = BooleanKey.of("vault-ignore-world", false); + + /* controls the settings for Vault primary group overrides. Likely to be removed in later versions */ public static final ConfigKey VAULT_PRIMARY_GROUP_OVERRIDES = BooleanKey.of("vault-primary-groups-overrides.enabled", false); public static final ConfigKey VAULT_PRIMARY_GROUP_OVERRIDES_CHECK_INHERITED = BooleanKey.of("vault-primary-groups-overrides.check-inherited-permissions", false); public static final ConfigKey VAULT_PRIMARY_GROUP_OVERRIDES_CHECK_EXISTS = BooleanKey.of("vault-primary-groups-overrides.check-group-exists", true); public static final ConfigKey VAULT_PRIMARY_GROUP_OVERRIDES_CHECK_MEMBER_OF = BooleanKey.of("vault-primary-groups-overrides.check-user-member-of", true); + + /** + * If Vault debug mode is enabled + */ public static final ConfigKey VAULT_DEBUG = BooleanKey.of("vault-debug", false); + + /** + * The world rewrites map + */ public static final ConfigKey> WORLD_REWRITES = MapKey.of("world-rewrite"); + + /** + * The group name rewrites map + */ public static final ConfigKey> GROUP_NAME_REWRITES = MapKey.of("group-name-rewrite"); + + /** + * The default assignments being applied by the plugin + */ public static final ConfigKey> DEFAULT_ASSIGNMENTS = AbstractKey.of(c -> { return c.getObjectList("default-assignments", ImmutableList.of()).stream().map(name -> { String hasTrue = c.getString("default-assignments." + name + ".if.has-true", null); @@ -174,6 +322,10 @@ public class ConfigKeys { return new Rule(hasTrue, hasFalse, lacks, give, take, pg); }).collect(ImmutableCollectors.toImmutableList()); }); + + /** + * The database settings, username, password, etc for use by any database + */ public static final ConfigKey DATABASE_VALUES = EnduringKey.wrap(AbstractKey.of(c -> { return new DatastoreConfiguration( c.getString("data.address", null), @@ -183,10 +335,30 @@ public class ConfigKeys { c.getInt("data.pool-size", 10) ); })); + + /** + * The prefix for any SQL tables + */ public static final ConfigKey SQL_TABLE_PREFIX = EnduringKey.wrap(StringKey.of("data.table_prefix", "luckperms_")); + + /** + * The name of the storage method being used + */ public static final ConfigKey STORAGE_METHOD = EnduringKey.wrap(LowercaseStringKey.of("storage-method", "h2")); + + /** + * If storage files should be monitored for changes + */ public static final ConfigKey WATCH_FILES = BooleanKey.of("watch-files", true); + + /** + * If split storage is being used + */ public static final ConfigKey SPLIT_STORAGE = EnduringKey.wrap(BooleanKey.of("split-storage.enabled", false)); + + /** + * The options for split storage + */ public static final ConfigKey> SPLIT_STORAGE_OPTIONS = EnduringKey.wrap(AbstractKey.of(c -> { return ImmutableMap.builder() .put("user", c.getString("split-storage.methods.user", "h2").toLowerCase()) @@ -196,32 +368,68 @@ public class ConfigKeys { .put("log", c.getString("split-storage.methods.log", "h2").toLowerCase()) .build(); })); + + /** + * The name of the messaging service in use, or "none" if not enabled. + */ public static final ConfigKey MESSAGING_SERVICE = EnduringKey.wrap(LowercaseStringKey.of("messaging-service", "none")); + + /** + * If updates should be automatically pushed by the messaging service + */ public static final ConfigKey AUTO_PUSH_UPDATES = EnduringKey.wrap(BooleanKey.of("auto-push-updates", true)); + + /** + * If redis messaging is enabled + */ public static final ConfigKey REDIS_ENABLED = EnduringKey.wrap(BooleanKey.of("redis.enabled", false)); + + /** + * The address of the redis server + */ public static final ConfigKey REDIS_ADDRESS = EnduringKey.wrap(StringKey.of("redis.address", null)); + + /** + * The password in use by the redis server, or an empty string if there is no passworld + */ public static final ConfigKey REDIS_PASSWORD = EnduringKey.wrap(StringKey.of("redis.password", "")); - public static List> getAllKeys() { - ImmutableList.Builder> keys = ImmutableList.builder(); + /** + * The URL of the web editor + */ + public static final ConfigKey WEB_EDITOR_URL_PATTERN = StringKey.of("", "https://lpedit.lucko.me/"); - try { - Field[] values = ConfigKeys.class.getFields(); - for (Field f : values) { - if (!Modifier.isStatic(f.getModifiers())) { - continue; - } + private static List> KEYS = null; - Object val = f.get(null); - if (val instanceof ConfigKey) { - keys.add((ConfigKey) val); + /** + * Gets all of the possible config keys defined in this class + * + * @return all of the possible config keys defined in this class + */ + public static synchronized List> getAllKeys() { + if (KEYS == null) { + ImmutableList.Builder> keys = ImmutableList.builder(); + + try { + Field[] values = ConfigKeys.class.getFields(); + for (Field f : values) { + if (!Modifier.isStatic(f.getModifiers())) { + continue; + } + + Object val = f.get(null); + if (val instanceof ConfigKey) { + keys.add((ConfigKey) val); + } } + } catch (Exception e) { + e.printStackTrace(); } - } catch (Exception e) { - e.printStackTrace(); + + KEYS = keys.build(); } - return keys.build(); + return KEYS; } }