Properly implement Contexts#allowAll - bump API to 3.3

This commit is contained in:
Luck 2017-08-13 22:21:04 +02:00
parent c598daf350
commit 82466c2e5d
No known key found for this signature in database
GPG Key ID: EFA9B3EC5FD90F8B
23 changed files with 353 additions and 33 deletions

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId>
<version>3.2-SNAPSHOT</version>
<version>3.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -39,16 +39,28 @@ import javax.annotation.Nonnull;
public class Contexts {
public static final String SERVER_KEY = "server";
public static final String WORLD_KEY = "world";
private static final Contexts ALLOW_ALL = new Contexts(ContextSet.empty(), true, true, true, true, true, true);
private static final Contexts GLOBAL = new Contexts(ContextSet.empty(), true, true, true, true, true, false);
/**
* Gets a context that will allow all nodes
* Gets the {@link FullySatisfiedContexts} instance.
*
* @return a context that will not apply any filters
* @return a context that will satisfy all contextual requirements.
*/
@Nonnull
public static Contexts allowAll() {
return ALLOW_ALL;
return FullySatisfiedContexts.getInstance();
}
/**
* A contexts instance with no defined context.
*
* @return the global contexts
* @since 3.3
*/
@Nonnull
public static Contexts global() {
return GLOBAL;
}
public static Contexts of(@Nonnull ContextSet context, boolean includeGlobal, boolean includeGlobalWorld, boolean applyGroups, boolean applyGlobalGroups, boolean applyGlobalWorldGroups, boolean op) {
@ -193,7 +205,9 @@ public class Contexts {
@Override
public boolean equals(Object o) {
if (o == this) return true;
if (o == allowAll()) return false;
if (!(o instanceof Contexts)) return false;
final Contexts other = (Contexts) o;
return this.getContexts().equals(other.getContexts()) &&
this.isOp() == other.isOp() &&
@ -209,7 +223,7 @@ public class Contexts {
final int PRIME = 59;
int result = 1;
final Object contexts = this.getContexts();
result = result * PRIME + (contexts == null ? 43 : contexts.hashCode());
result = result * PRIME + contexts.hashCode();
result = result * PRIME + (this.isOp() ? 79 : 97);
result = result * PRIME + (this.isIncludeGlobal() ? 79 : 97);
result = result * PRIME + (this.isIncludeGlobalWorld() ? 79 : 97);

View File

@ -0,0 +1,51 @@
package me.lucko.luckperms.api;
import me.lucko.luckperms.api.caching.MetaContexts;
import me.lucko.luckperms.api.caching.UserData;
import me.lucko.luckperms.api.context.ContextSet;
import javax.annotation.Nonnull;
/**
* A special instance of {@link Contexts}, which when passed to:
*
* <p><ul>
* <li>{@link UserData#getPermissionData(Contexts)}</li>
* <li>{@link UserData#getMetaData(Contexts)}</li>
* <li>{@link UserData#getMetaData(MetaContexts)}</li>
* </ul></p>
*
* <p>will always satisfy all contextual requirements.</p>
*
* <p>This effectively allows you to do lookups which ignore context.</p>
*
* @since 3.3
*/
public final class FullySatisfiedContexts extends Contexts {
private static final FullySatisfiedContexts INSTANCE = new FullySatisfiedContexts();
@Nonnull
public static Contexts getInstance() {
return INSTANCE;
}
private FullySatisfiedContexts() {
super(ContextSet.empty(), true, true, true, true, true, false);
}
@Nonnull
@Override
public String toString() {
return "FullySatisfiedContexts";
}
@Override
public boolean equals(Object o) {
return o == this;
}
@Override
public int hashCode() {
return System.identityHashCode(this);
}
}

View File

@ -173,4 +173,24 @@ public interface LPConfiguration {
@Nonnull
Map<String, String> getSplitStorageOptions();
@Nonnull
Unsafe unsafe();
interface Unsafe {
/**
* Gets an Object from the config.
*
* <p>This method is nested under {@link Unsafe} because the keys
* and return types may change between versions without warning.</p>
*
* @param key the key, as defined as a parameter name in
* the "ConfigKeys" class.
* @return the corresponding object, if one is present
* @throws IllegalArgumentException if the key isn't known
*/
@Nonnull
Object getObject(String key);
}
}

View File

@ -328,4 +328,31 @@ public interface LuckPermsApi {
@Nonnull
ContextSet getContextForPlayer(@Nonnull Object player);
/**
* Gets a Contexts instance for the player using the platforms {@link ContextCalculator}s.
*
* @param player the player to calculate for. Must be the player instance for the platform.
* @return a set of contexts.
* @since 3.3
*/
@Nonnull
Contexts getContextsForPlayer(@Nonnull Object player);
/**
* Gets the unique players which have connected to the server since it started.
*
* @return the unique connections
* @since 3.3
*/
@Nonnull
Set<UUID> getUniqueConnections();
/**
* Gets the time when the plugin first started in milliseconds.
*
* @return the enable time
* @since 3.3
*/
long getStartTime();
}

View File

@ -25,10 +25,15 @@
package me.lucko.luckperms.api;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.Multimap;
import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.api.context.ImmutableContextSet;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
@ -67,6 +72,47 @@ public interface PermissionHolder {
@Nonnull
String getFriendlyName();
/**
* Gets the backing multimap containing every permission this holder has.
*
* <p>This method <b>does not</b> resolve inheritance rules, and returns a
* view of what's 'in the file'.</p>
*
* @return the holders own permissions
* @since 3.3
*/
@Nonnull
ImmutableSetMultimap<ImmutableContextSet, Node> getNodes();
/**
* Gets the backing multimap containing every transient permission this holder has.
*
* <p>This method <b>does not</b> resolve inheritance rules.</p>
*
* <p>Transient permissions only exist for the duration of the session.</p>
*
* @return the holders own permissions
* @since 3.3
*/
@Nonnull
ImmutableSetMultimap<ImmutableContextSet, Node> getTransientNodes();
/**
* Gets a flattened/squashed view of the holders permissions.
*
* <p>This list is constructed using the {@link Multimap#values()} method
* of both the transient and enduring backing multimaps.</p>
*
* <p>This means that it <b>may contain</b> duplicate entries.</p>
*
* <p>Use {@link #getPermissions()} for a view without duplicates.</p>
*
* @return a list of the holders own nodes.
* @since 3.3
*/
@Nonnull
List<Node> getOwnNodes();
/**
* Gets a sorted set of all held permissions.
*
@ -116,6 +162,38 @@ public interface PermissionHolder {
@Nonnull
Set<Node> getTemporaryPermissionNodes();
/**
* Recursively resolves this holders permissions.
*
* <p>The returned list will contain every inherited
* node the holder has, in the order that they were inherited in.</p>
*
* <p>This means the list will contain duplicates.</p>
*
* @param contexts the contexts for the lookup
* @return a list of nodes
* @since 3.3
*/
@Nonnull
List<LocalizedNode> resolveInheritances(Contexts contexts);
/**
* Recursively resolves this holders permissions.
*
* <p>The returned list will contain every inherited
* node the holder has, in the order that they were inherited in.</p>
*
* <p>This means the list will contain duplicates.</p>
*
* <p>Unlike {@link #resolveInheritances(Contexts)}, this method does not
* filter by context, at all.</p>
*
* @return a list of nodes
* @since 3.3
*/
@Nonnull
List<LocalizedNode> resolveInheritances();
/**
* Gets a mutable sorted set of the nodes that this object has and inherits, filtered by context
*
@ -132,6 +210,20 @@ public interface PermissionHolder {
@Nonnull
SortedSet<LocalizedNode> getAllNodes(@Nonnull Contexts contexts);
/**
* Gets a mutable sorted set of the nodes that this object has and inherits.
*
* <p>Unlike {@link #getAllNodes(Contexts)}, this method does not filter by context, at all.</p>
*
* <p>Nodes are sorted into priority order.</p>
*
* @return a mutable sorted set of permissions
* @throws NullPointerException if the context is null
* @since 3.3
*/
@Nonnull
SortedSet<LocalizedNode> getAllNodes();
/**
* Gets a mutable set of the nodes that this object has and inherits, filtered by context.
*

View File

@ -129,12 +129,13 @@ public interface User extends PermissionHolder {
Optional<UserData> getUserDataCache();
/**
* Sets up the users data cache, if the don't have one setup already.
* Pre-calculates some values in the user's data cache.
*
* <p>Is it <b>not</b> necessary to call this method before
* using {@link #getCachedData()}.</p>
*
* @since 2.17
* @deprecated in version 3.2, as this cache is now always loaded.
*/
@Deprecated
void setupDataCache();
/**

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId>
<version>3.2-SNAPSHOT</version>
<version>3.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId>
<version>3.2-SNAPSHOT</version>
<version>3.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId>
<version>3.2-SNAPSHOT</version>
<version>3.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId>
<version>3.2-SNAPSHOT</version>
<version>3.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -53,6 +53,7 @@ import me.lucko.luckperms.common.messaging.NoopMessagingService;
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
import me.lucko.luckperms.common.references.UserIdentifier;
import java.util.Collections;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
@ -87,7 +88,7 @@ public class ApiProvider implements LuckPermsApi {
@Override
public double getApiVersion() {
return 3.2;
return 3.3;
}
@Override
@ -231,4 +232,20 @@ public class ApiProvider implements LuckPermsApi {
public ContextSet getContextForPlayer(@NonNull Object player) {
return plugin.getContextManager().getApplicableContext(player);
}
@SuppressWarnings("unchecked")
@Override
public Contexts getContextsForPlayer(@NonNull Object player) {
return plugin.getContextManager().getApplicableContexts(player);
}
@Override
public Set<UUID> getUniqueConnections() {
return Collections.unmodifiableSet(plugin.getUniqueConnections());
}
@Override
public long getStartTime() {
return plugin.getStartTime();
}
}

View File

@ -25,10 +25,9 @@
package me.lucko.luckperms.common.api.delegates;
import lombok.AllArgsConstructor;
import me.lucko.luckperms.api.LPConfiguration;
import me.lucko.luckperms.api.data.DatastoreConfiguration;
import me.lucko.luckperms.common.config.ConfigKey;
import me.lucko.luckperms.common.config.ConfigKeys;
import me.lucko.luckperms.common.config.LuckPermsConfiguration;
@ -37,9 +36,14 @@ import java.util.Map;
/**
* Provides a link between {@link LPConfiguration} and {@link LuckPermsConfiguration}
*/
@AllArgsConstructor
public class LPConfigurationDelegate implements LPConfiguration {
private final LuckPermsConfiguration handle;
private final Unsafe unsafe;
public LPConfigurationDelegate(LuckPermsConfiguration handle) {
this.handle = handle;
this.unsafe = new UnsafeImpl();
}
@Override
public String getServer() {
@ -140,4 +144,21 @@ public class LPConfigurationDelegate implements LPConfiguration {
public Map<String, String> getSplitStorageOptions() {
return handle.get(ConfigKeys.SPLIT_STORAGE_OPTIONS);
}
@Override
public Unsafe unsafe() {
return unsafe;
}
private final class UnsafeImpl implements Unsafe {
@Override
public Object getObject(String key) {
ConfigKey<?> configKey = ConfigKeys.getAllKeys().get(key.toUpperCase());
if (configKey == null) {
throw new IllegalArgumentException("Unknown key: " + key);
}
return handle.get(configKey);
}
}
}

View File

@ -29,6 +29,7 @@ import lombok.AllArgsConstructor;
import lombok.NonNull;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.ImmutableSortedSet;
import me.lucko.luckperms.api.Contexts;
@ -38,6 +39,7 @@ import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.PermissionHolder;
import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.api.context.ContextSet;
import me.lucko.luckperms.api.context.ImmutableContextSet;
import me.lucko.luckperms.api.context.MutableContextSet;
import me.lucko.luckperms.common.contexts.ExtractedContexts;
import me.lucko.luckperms.common.model.User;
@ -47,6 +49,7 @@ import me.lucko.luckperms.exceptions.ObjectLacksException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
@ -72,6 +75,21 @@ public class PermissionHolderDelegate implements PermissionHolder {
return handle.getFriendlyName();
}
@Override
public ImmutableSetMultimap<ImmutableContextSet, Node> getNodes() {
return handle.getEnduringNodes();
}
@Override
public ImmutableSetMultimap<ImmutableContextSet, Node> getTransientNodes() {
return handle.getTransientNodes();
}
@Override
public List<Node> getOwnNodes() {
return handle.getOwnNodes();
}
@Override
public SortedSet<? extends Node> getPermissions() {
return ImmutableSortedSet.copyOfSorted(handle.getOwnNodesSorted());
@ -92,6 +110,11 @@ public class PermissionHolderDelegate implements PermissionHolder {
return new TreeSet<>(handle.resolveInheritancesAlmostEqual(ExtractedContexts.generate(contexts)));
}
@Override
public SortedSet<LocalizedNode> getAllNodes() {
return new TreeSet<>(handle.resolveInheritancesAlmostEqual());
}
@Override
public Set<LocalizedNode> getAllNodesFiltered(@NonNull Contexts contexts) {
return new HashSet<>(handle.getAllNodes(ExtractedContexts.generate(contexts)));
@ -412,6 +435,16 @@ public class PermissionHolderDelegate implements PermissionHolder {
return handle.getTemporaryNodes();
}
@Override
public List<LocalizedNode> resolveInheritances(Contexts contexts) {
return null;
}
@Override
public List<LocalizedNode> resolveInheritances() {
return null;
}
@Override
public Set<Node> getPermanentPermissionNodes() {
return handle.getPermanentNodes();

View File

@ -86,14 +86,26 @@ public class UserCache implements UserData {
@Override
public PermissionCache calculatePermissions(@NonNull Contexts contexts) {
PermissionCache data = new PermissionCache(contexts, user, user.getPlugin().getCalculatorFactory());
data.setPermissions(user.exportNodesAndShorthand(ExtractedContexts.generate(contexts), true));
if (contexts == Contexts.allowAll()) {
data.setPermissions(user.exportNodesAndShorthand(true));
} else {
data.setPermissions(user.exportNodesAndShorthand(ExtractedContexts.generate(contexts), true));
}
return data;
}
@Override
public MetaCache calculateMeta(@NonNull MetaContexts contexts) {
MetaCache data = new MetaCache();
data.loadMeta(user.accumulateMeta(newAccumulator(contexts), null, ExtractedContexts.generate(contexts.getContexts())));
if (contexts.getContexts() == Contexts.allowAll()) {
data.loadMeta(user.accumulateMeta(newAccumulator(contexts), null));
} else {
data.loadMeta(user.accumulateMeta(newAccumulator(contexts), null, ExtractedContexts.generate(contexts.getContexts())));
}
return data;
}
@ -169,7 +181,12 @@ public class UserCache implements UserData {
@Override
public PermissionCache reload(Contexts contexts, PermissionCache oldData) {
oldData.comparePermissions(user.exportNodesAndShorthand(ExtractedContexts.generate(contexts), true));
if (contexts == Contexts.allowAll()) {
oldData.comparePermissions(user.exportNodesAndShorthand(true));
} else {
oldData.comparePermissions(user.exportNodesAndShorthand(ExtractedContexts.generate(contexts), true));
}
return oldData;
}
}
@ -182,7 +199,12 @@ public class UserCache implements UserData {
@Override
public MetaCache reload(MetaContexts contexts, MetaCache oldData) {
oldData.loadMeta(user.accumulateMeta(newAccumulator(contexts), null, ExtractedContexts.generate(contexts.getContexts())));
if (contexts.getContexts() == Contexts.allowAll()) {
oldData.loadMeta(user.accumulateMeta(newAccumulator(contexts), null));
} else {
oldData.loadMeta(user.accumulateMeta(newAccumulator(contexts), null, ExtractedContexts.generate(contexts.getContexts())));
}
return oldData;
}
}

View File

@ -64,7 +64,7 @@ public abstract class AbstractConfiguration implements LuckPermsConfiguration {
@Override
public void loadAll() {
ConfigKeys.getAllKeys().forEach(cache::get);
ConfigKeys.getAllKeys().values().forEach(cache::get);
contextsFile.load();
}

View File

@ -54,6 +54,7 @@ import me.lucko.luckperms.common.utils.ImmutableCollectors;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
@ -420,16 +421,16 @@ public class ConfigKeys {
*/
public static final ConfigKey<String> WEB_EDITOR_URL_PATTERN = StringKey.of("web-editor-url", "https://lpedit.lucko.me/");
private static List<ConfigKey<?>> KEYS = null;
private static Map<String, ConfigKey<?>> KEYS = null;
/**
* 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<ConfigKey<?>> getAllKeys() {
public static synchronized Map<String, ConfigKey<?>> getAllKeys() {
if (KEYS == null) {
ImmutableList.Builder<ConfigKey<?>> keys = ImmutableList.builder();
Map<String, ConfigKey<?>> keys = new LinkedHashMap<>();
try {
Field[] values = ConfigKeys.class.getFields();
@ -440,14 +441,14 @@ public class ConfigKeys {
Object val = f.get(null);
if (val instanceof ConfigKey<?>) {
keys.add((ConfigKey<?>) val);
keys.put(f.getName(), (ConfigKey<?>) val);
}
}
} catch (Exception e) {
e.printStackTrace();
}
KEYS = keys.build();
KEYS = ImmutableMap.copyOf(keys);
}
return KEYS;

View File

@ -717,6 +717,27 @@ public abstract class PermissionHolder {
return ImmutableMap.copyOf(perms);
}
public Map<String, Boolean> exportNodesAndShorthand(boolean lowerCase) {
List<LocalizedNode> entries = resolveInheritances();
Map<String, Boolean> perms = new HashMap<>();
boolean applyShorthand = plugin.getConfiguration().get(ConfigKeys.APPLYING_SHORTHAND);
for (Node node : entries) {
String perm = lowerCase ? node.getPermission().toLowerCase() : node.getPermission();
if (perms.putIfAbsent(perm, node.getValue()) == null) {
if (applyShorthand) {
List<String> sh = node.resolveShorthand();
if (!sh.isEmpty()) {
sh.stream().map(s -> lowerCase ? s.toLowerCase() : s).forEach(s -> perms.putIfAbsent(s, node.getValue()));
}
}
}
}
return ImmutableMap.copyOf(perms);
}
public MetaAccumulator accumulateMeta(MetaAccumulator accumulator, Set<String> excludedGroups, ExtractedContexts context) {
if (accumulator == null) {
accumulator = MetaAccumulator.makeFromConfig(plugin);

View File

@ -6,7 +6,7 @@
<groupId>me.lucko.luckperms</groupId>
<artifactId>luckperms</artifactId>
<version>3.2-SNAPSHOT</version>
<version>3.3-SNAPSHOT</version>
<modules>
<module>api</module>
@ -47,7 +47,7 @@
<maven.test.skip>true</maven.test.skip>
<!-- Manually entered release version -->
<release.version>3.2</release.version>
<release.version>3.3</release.version>
<!-- Get how many commits have been made since the last tag (the previous release) -->
<patch.version>${git.closest.tag.commit.count}</patch.version>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId>
<version>3.2-SNAPSHOT</version>
<version>3.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId>
<version>3.2-SNAPSHOT</version>
<version>3.3-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId>
<version>3.2-SNAPSHOT</version>
<version>3.3-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId>
<version>3.2-SNAPSHOT</version>
<version>3.3-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>