Proper context implementation - WIP

This commit is contained in:
Luck
2016-09-25 10:19:36 +01:00
Unverified
parent d8221f466a
commit 5ee6db02ff
51 changed files with 1019 additions and 202 deletions
@@ -27,8 +27,9 @@ import me.lucko.luckperms.api.PlatformType;
import me.lucko.luckperms.api.implementation.ApiProvider;
import me.lucko.luckperms.commands.ConsecutiveExecutor;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.config.LPConfiguration;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.core.LPConfiguration;
import me.lucko.luckperms.contexts.ContextManager;
import me.lucko.luckperms.core.UuidCache;
import me.lucko.luckperms.data.Importer;
import me.lucko.luckperms.groups.GroupManager;
@@ -62,6 +63,7 @@ public interface LuckPermsPlugin {
Importer getImporter();
ConsecutiveExecutor getConsecutiveExecutor();
LocaleManager getLocaleManager();
ContextManager getContextManager();
/**
* @return the version of the plugin
@@ -27,6 +27,8 @@ import lombok.AllArgsConstructor;
import lombok.NonNull;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.api.*;
import me.lucko.luckperms.api.context.ContextListener;
import me.lucko.luckperms.api.context.IContextCalculator;
import me.lucko.luckperms.api.event.LPEvent;
import me.lucko.luckperms.api.event.LPListener;
import me.lucko.luckperms.api.implementation.internal.*;
@@ -208,6 +210,18 @@ public class ApiProvider implements LuckPermsApi {
@Override
public Node.Builder buildNode(@NonNull String permission) throws IllegalArgumentException {
return new me.lucko.luckperms.utils.Node.Builder(checkNode(permission));
return new me.lucko.luckperms.core.Node.Builder(checkNode(permission));
}
@SuppressWarnings("unchecked")
@Override
public void registerContextCalculator(IContextCalculator<?> contextCalculator) {
plugin.getContextManager().registerCalculator(contextCalculator);
}
@SuppressWarnings("unchecked")
@Override
public void registerContextListener(ContextListener<?> contextListener) {
plugin.getContextManager().registerListener(contextListener);
}
}
@@ -30,11 +30,11 @@ import me.lucko.luckperms.api.data.MySQLConfiguration;
import java.util.Map;
/**
* Provides a link between {@link LPConfiguration} and {@link me.lucko.luckperms.core.LPConfiguration}
* Provides a link between {@link LPConfiguration} and {@link me.lucko.luckperms.config.LPConfiguration}
*/
@AllArgsConstructor
public class LPConfigurationLink implements LPConfiguration {
private final me.lucko.luckperms.core.LPConfiguration master;
private final me.lucko.luckperms.config.LPConfiguration master;
@Override
public String getServer() {
@@ -27,9 +27,9 @@ import lombok.NonNull;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.PermissionHolder;
import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.contexts.Contexts;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import me.lucko.luckperms.utils.Contexts;
import java.util.*;
@@ -253,7 +253,16 @@ public class PermissionHolderLink implements PermissionHolder {
@Override
public Map<String, Boolean> getPermissions(String server, String world, Map<String, String> extraContext, boolean includeGlobal, List<String> possibleNodes, boolean applyGroups) {
return master.exportNodes(new Contexts(server, world, extraContext, includeGlobal, includeGlobal, applyGroups, true, true), possibleNodes);
if (extraContext == null) {
extraContext = new HashMap<>();
}
if (server != null && !server.equals("")) {
extraContext.put("server", server);
}
if (world != null && !world.equals("")) {
extraContext.put("world", world);
}
return master.exportNodes(new Contexts(extraContext, includeGlobal, includeGlobal, applyGroups, true, true), possibleNodes);
}
@Override
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.utils;
package me.lucko.luckperms.calculators;
import lombok.AllArgsConstructor;
import lombok.Getter;
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.utils;
package me.lucko.luckperms.calculators;
import me.lucko.luckperms.api.Tristate;
@@ -27,8 +27,8 @@ import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.commands.*;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.contexts.Contexts;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.utils.Contexts;
import java.util.*;
@@ -26,9 +26,9 @@ import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.CommandResult;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SingleMainCommand;
import me.lucko.luckperms.config.LPConfiguration;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.core.LPConfiguration;
import java.util.List;
@@ -27,8 +27,8 @@ import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.commands.*;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.contexts.Contexts;
import me.lucko.luckperms.users.User;
import me.lucko.luckperms.utils.Contexts;
import java.util.AbstractMap.SimpleEntry;
import java.util.List;
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.core;
package me.lucko.luckperms.config;
import com.google.common.collect.ImmutableMap;
import lombok.AccessLevel;
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
package me.lucko.luckperms.core;
package me.lucko.luckperms.config;
import me.lucko.luckperms.storage.DatastoreConfiguration;
@@ -0,0 +1,65 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.contexts;
import me.lucko.luckperms.api.context.ContextListener;
import me.lucko.luckperms.api.context.IContextCalculator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
public class ContextManager<T> {
private final List<IContextCalculator<T>> calculators = new CopyOnWriteArrayList<>();
private final List<ContextListener<T>> listeners = new CopyOnWriteArrayList<>();
public void registerCalculator(IContextCalculator<T> calculator) {
listeners.forEach(calculator::addListener);
calculators.add(calculator);
}
public void registerListener(ContextListener<T> listener) {
for (IContextCalculator<T> calculator : calculators) {
calculator.addListener(listener);
}
listeners.add(listener);
}
public Map<String, String> giveApplicableContext(T subject, Map<String, String> accumulator) {
for (IContextCalculator<T> calculator : calculators) {
calculator.giveApplicableContext(subject, accumulator);
}
return accumulator;
}
public boolean isContextApplicable(T subject, Map.Entry<String, String> context) {
for (IContextCalculator<T> calculator : calculators) {
if (calculator.isContextApplicable(subject, context)) {
return true;
}
}
return false;
}
}
@@ -20,11 +20,10 @@
* SOFTWARE.
*/
package me.lucko.luckperms.utils;
package me.lucko.luckperms.contexts;
import lombok.AllArgsConstructor;
import lombok.Getter;
import me.lucko.luckperms.core.LPConfiguration;
import java.util.Collections;
import java.util.Map;
@@ -32,26 +31,11 @@ import java.util.Map;
@Getter
@AllArgsConstructor
public class Contexts {
public static Contexts fromConfig(LPConfiguration configuration) {
return new Contexts(
configuration.getServer(),
null,
Collections.emptyMap(),
configuration.isIncludingGlobalPerms(),
configuration.isIncludingGlobalWorldPerms(),
true,
configuration.isApplyingGlobalGroups(),
configuration.isApplyingGlobalWorldGroups()
);
}
public static Contexts allowAll() {
return new Contexts(null, null, Collections.emptyMap(), true, true, true, true, true);
return new Contexts(Collections.emptyMap(), true, true, true, true, true);
}
private final String server;
private final String world;
private final Map<String, String> extraContext;
private final Map<String, String> context;
private final boolean includeGlobal;
private final boolean includeGlobalWorld;
private final boolean applyGroups;
@@ -0,0 +1,44 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.contexts;
import lombok.AllArgsConstructor;
import me.lucko.luckperms.api.context.ContextCalculator;
import java.util.Map;
@AllArgsConstructor
public class ServerCalculator<T> extends ContextCalculator<T> {
private final String server;
@Override
public Map<String, String> giveApplicableContext(T subject, Map<String, String> accumulator) {
accumulator.put("server", server);
return accumulator;
}
@Override
public boolean isContextApplicable(T subject, Map.Entry<String, String> context) {
return context.getKey().equals("server") && server.equals(context.getValue());
}
}
@@ -20,13 +20,14 @@
* SOFTWARE.
*/
package me.lucko.luckperms.utils;
package me.lucko.luckperms.core;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableMap;
import lombok.*;
import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.constants.Patterns;
import me.lucko.luckperms.utils.ArgumentChecker;
import java.util.*;
import java.util.regex.Pattern;
@@ -100,7 +101,7 @@ public class Node implements me.lucko.luckperms.api.Node {
private long expireAt = 0L;
private final Map<String, String> extraContexts = new HashMap<>();
private final Map<String, String> extraContexts;
// Cache the state
private Tristate isPrefix = Tristate.UNDEFINED;
@@ -140,9 +141,11 @@ public class Node implements me.lucko.luckperms.api.Node {
this.server = server;
this.world = world;
ImmutableMap.Builder<String, String> contexts = ImmutableMap.builder();
if (extraContexts != null) {
this.extraContexts.putAll(extraContexts);
contexts.putAll(extraContexts);
}
this.extraContexts = contexts.build();
}
@Override
@@ -225,36 +228,65 @@ public class Node implements me.lucko.luckperms.api.Node {
}
@Override
public boolean shouldApplyWithContext(Map<String, String> context) {
if (context == null || context.isEmpty()) {
public boolean shouldApplyWithContext(Map<String, String> context, boolean worldAndServer) {
if (extraContexts.isEmpty() && !isServerSpecific() && !isWorldSpecific()) {
return true;
}
for (Map.Entry<String, String> c : context.entrySet()) {
if (c.getKey().equals("server")) {
if (shouldApplyOnServer(c.getValue(), false, false)) {
if (worldAndServer) {
if (isWorldSpecific()) {
if (context == null) {
return false;
}
if (!context.containsKey("world")) {
return false;
}
if (!context.get("world").equalsIgnoreCase(world)) {
return false;
}
}
if (c.getKey().equals("world")) {
if (shouldApplyOnWorld(c.getValue(), false, false)) {
if (isServerSpecific()) {
if (context == null) {
return false;
}
if (!context.containsKey("server")) {
return false;
}
if (!context.get("server").equalsIgnoreCase(server)) {
return false;
}
}
}
if (!getExtraContexts().containsKey(c.getKey())) {
if (!extraContexts.isEmpty()) {
if (context == null) {
return false;
}
if (!getExtraContexts().get(c.getKey()).equalsIgnoreCase(c.getValue())) {
return false;
for (Map.Entry<String, String> c : extraContexts.entrySet()) {
if (!context.containsKey(c.getKey())) {
return false;
}
if (!context.get(c.getKey()).equalsIgnoreCase(c.getValue())) {
return false;
}
}
}
return true;
}
@Override
public boolean shouldApplyWithContext(Map<String, String> context) {
return shouldApplyWithContext(context, true);
}
@Override
public boolean shouldApplyOnAnyServers(List<String> servers, boolean includeGlobal) {
for (String s : servers) {
@@ -33,10 +33,10 @@ import me.lucko.luckperms.api.event.events.PermissionNodeExpireEvent;
import me.lucko.luckperms.api.event.events.PermissionNodeSetEvent;
import me.lucko.luckperms.api.event.events.PermissionNodeUnsetEvent;
import me.lucko.luckperms.api.implementation.internal.PermissionHolderLink;
import me.lucko.luckperms.contexts.Contexts;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.utils.Contexts;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
@@ -157,16 +157,27 @@ public abstract class PermissionHolder {
.filter(Node::isGroupNode)
.collect(Collectors.toSet());
Map<String, String> contexts = new HashMap<>(context.getContext());
String server = contexts.get("server");
String world = contexts.get("world");
contexts.remove("server");
contexts.remove("world");
Iterator<Node> iterator = parents.iterator();
while (iterator.hasNext()) {
Node node = iterator.next();
if (!node.shouldApplyOnServer(context.getServer(), context.isApplyGlobalGroups(), plugin.getConfiguration().isApplyingRegex())) {
if (!node.shouldApplyOnServer(server, context.isApplyGlobalGroups(), plugin.getConfiguration().isApplyingRegex())) {
iterator.remove();
continue;
}
if (!node.shouldApplyOnWorld(context.getWorld(), context.isApplyGlobalWorldGroups(), plugin.getConfiguration().isApplyingRegex())) {
if (!node.shouldApplyOnWorld(world, context.isApplyGlobalWorldGroups(), plugin.getConfiguration().isApplyingRegex())) {
iterator.remove();
continue;
}
if (!node.shouldApplyWithContext(contexts, false)) {
iterator.remove();
continue;
}
@@ -212,17 +223,23 @@ public abstract class PermissionHolder {
allNodes = getPermissions(true);
}
Map<String, String> contexts = new HashMap<>(context.getContext());
String server = contexts.get("server");
String world = contexts.get("world");
contexts.remove("server");
contexts.remove("world");
all:
for (Node node : allNodes) {
if (!node.shouldApplyOnServer(context.getServer(), context.isIncludeGlobal(), plugin.getConfiguration().isApplyingRegex())) {
if (!node.shouldApplyOnServer(server, context.isIncludeGlobal(), plugin.getConfiguration().isApplyingRegex())) {
continue;
}
if (!node.shouldApplyOnWorld(context.getWorld(), context.isIncludeGlobalWorld(), plugin.getConfiguration().isApplyingRegex())) {
if (!node.shouldApplyOnWorld(world, context.isIncludeGlobalWorld(), plugin.getConfiguration().isApplyingRegex())) {
continue;
}
if (!node.shouldApplyWithContext(context.getExtraContext())) {
if (!node.shouldApplyWithContext(contexts, false)) {
continue;
}
@@ -299,7 +316,7 @@ public abstract class PermissionHolder {
// Convenience method
private static Node.Builder buildNode(String permission) {
return new me.lucko.luckperms.utils.Node.Builder(permission);
return new me.lucko.luckperms.core.Node.Builder(permission);
}
@Deprecated
@@ -307,7 +324,7 @@ public abstract class PermissionHolder {
this.nodes.clear();
this.nodes.addAll(nodes.entrySet().stream()
.map(e -> me.lucko.luckperms.utils.Node.fromSerialisedNode(e.getKey(), e.getValue()))
.map(e -> me.lucko.luckperms.core.Node.fromSerialisedNode(e.getKey(), e.getValue()))
.collect(Collectors.toList()));
auditTemporaryPermissions();
@@ -552,12 +569,26 @@ public abstract class PermissionHolder {
*/
@Deprecated
public Map<String, Boolean> getLocalPermissions(String server, String world, List<String> excludedGroups, List<String> possibleNodes) {
return exportNodes(new Contexts(server, world, Collections.emptyMap(), plugin.getConfiguration().isIncludingGlobalPerms(), true, true, true, true), Collections.emptyList());
Map<String, String> context = new HashMap<>();
if (server != null && !server.equals("")) {
context.put("server", server);
}
if (world != null && !world.equals("")) {
context.put("world", world);
}
return exportNodes(new Contexts(context, plugin.getConfiguration().isIncludingGlobalPerms(), true, true, true, true), Collections.emptyList());
}
@Deprecated
public Map<String, Boolean> getLocalPermissions(String server, String world, List<String> excludedGroups) {
return exportNodes(new Contexts(server, world, Collections.emptyMap(), plugin.getConfiguration().isIncludingGlobalPerms(), true, true, true, true), Collections.emptyList());
Map<String, String> context = new HashMap<>();
if (server != null && !server.equals("")) {
context.put("server", server);
}
if (world != null && !world.equals("")) {
context.put("world", world);
}
return exportNodes(new Contexts(context, plugin.getConfiguration().isIncludingGlobalPerms(), true, true, true, true), Collections.emptyList());
}
@SuppressWarnings("deprecation")
@@ -26,10 +26,10 @@ import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import lombok.Cleanup;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.core.Node;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.tracks.Track;
import me.lucko.luckperms.users.User;
import me.lucko.luckperms.utils.Node;
import java.io.*;
import java.util.*;
@@ -24,10 +24,10 @@ package me.lucko.luckperms.storage.methods;
import lombok.Cleanup;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.core.Node;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.tracks.Track;
import me.lucko.luckperms.users.User;
import me.lucko.luckperms.utils.Node;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;