Fix no permissions applying when include-global is false, and better support per-server/per-world groups

This commit is contained in:
Luck 2016-09-17 19:05:56 +01:00
parent e7a210dc06
commit 30ea5a5b69
No known key found for this signature in database
GPG Key ID: EFA9B3EC5FD90F8B
16 changed files with 206 additions and 58 deletions

View File

@ -30,6 +30,7 @@ import me.lucko.luckperms.core.PermissionHolder;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.users.User;
import me.lucko.luckperms.utils.Contexts;
import net.milkbowl.vault.chat.Chat;
import java.util.Iterator;
@ -162,7 +163,7 @@ public class VaultChatHook extends Chat {
int priority = Integer.MIN_VALUE;
String meta = null;
for (Node n : holder.getAllNodes(null)) {
for (Node n : holder.getAllNodes(null, Contexts.allowAll())) {
if (!n.getValue()) {
continue;
}

View File

@ -28,6 +28,7 @@ import me.lucko.luckperms.LPBukkitPlugin;
import me.lucko.luckperms.api.event.events.UserPermissionRefreshEvent;
import me.lucko.luckperms.api.implementation.internal.UserLink;
import me.lucko.luckperms.inject.LPPermissible;
import me.lucko.luckperms.utils.Contexts;
import org.bukkit.permissions.Permissible;
import java.util.Collections;
@ -53,18 +54,23 @@ public class BukkitUser extends User {
@SuppressWarnings("unchecked")
@Override
public void refreshPermissions() {
public synchronized void refreshPermissions() {
if (lpPermissible == null) {
return;
}
// Calculate the permissions that should be applied. This is done async, who cares about how long it takes or how often it's done.
Map<String, Boolean> toApply = exportNodes(
getPlugin().getConfiguration().getServer(),
plugin.getUserManager().getWorldCache().get(getUuid()),
null,
plugin.getConfiguration().getIncludeGlobalPerms(),
true,
new Contexts(
getPlugin().getConfiguration().getServer(),
plugin.getUserManager().getWorldCache().get(getUuid()),
null,
getPlugin().getConfiguration().getIncludeGlobalPerms(),
getPlugin().getConfiguration().getIncludeGlobalWorldPerms(),
true,
getPlugin().getConfiguration().getApplyGlobalGroups(),
getPlugin().getConfiguration().getApplyGlobalWorldGroups()
),
Collections.emptyList()
);

View File

@ -8,9 +8,20 @@
# The name of the server, used for server specific permissions. Set to 'global' to disable.
server: global
# If users on this server should have their global permissions/groups applied.
# If users on this server should have their global permissions applied.
# If set to false, only server specific permissions will apply for users on this server
include-global: true
# If users on this server should have their global world permissions applied.
# If set to false, only world specific permissions will apply for users on this server
include-global-world: true
# If users on this server should have global (non-server specific) groups applied
apply-global-groups: true
# If users on this server should have global (non-world specific) groups applied
apply-global-world-groups: true
# If this server is in offline or online mode.
# This setting allows a player to have the same UUID across a network of offline mode/mixed servers.

View File

@ -26,6 +26,7 @@ import me.lucko.luckperms.BungeePlayerCache;
import me.lucko.luckperms.LPBungeePlugin;
import me.lucko.luckperms.api.event.events.UserPermissionRefreshEvent;
import me.lucko.luckperms.api.implementation.internal.UserLink;
import me.lucko.luckperms.utils.Contexts;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.util.Collections;
@ -46,7 +47,7 @@ public class BungeeUser extends User {
}
@Override
public void refreshPermissions() {
public synchronized void refreshPermissions() {
ProxiedPlayer player = plugin.getProxy().getPlayer(plugin.getUuidCache().getExternalUUID(getUuid()));
if (player == null) {
return;
@ -61,11 +62,16 @@ public class BungeeUser extends User {
// Calculate the permissions that should be applied. This is done async.
Map<String, Boolean> toApply = exportNodes(
plugin.getConfiguration().getServer(),
server,
null,
plugin.getConfiguration().getIncludeGlobalPerms(),
true,
new Contexts(
plugin.getConfiguration().getServer(),
server,
null,
plugin.getConfiguration().getIncludeGlobalPerms(),
plugin.getConfiguration().getIncludeGlobalWorldPerms(),
true,
plugin.getConfiguration().getApplyGlobalGroups(),
plugin.getConfiguration().getApplyGlobalWorldGroups()
),
Collections.emptyList()
);

View File

@ -8,9 +8,20 @@
# The name of the server, used for server specific permissions. Set to 'global' to disable.
server: bungee
# If users on this server should have their global permissions/groups applied.
# If users on this server should have their global permissions applied.
# If set to false, only server specific permissions will apply for users on this server
include-global: false
# If users on this server should have their global world permissions applied.
# If set to false, only world specific permissions will apply for users on this server
include-global-world: true
# If users on this server should have global (non-server specific) groups applied
apply-global-groups: true
# If users on this server should have global (non-world specific) groups applied
apply-global-world-groups: true
# If this server is in offline or online mode.
# This setting allows a player to have the same UUID across a network of offline mode/mixed servers.

View File

@ -29,6 +29,7 @@ import me.lucko.luckperms.api.PermissionHolder;
import me.lucko.luckperms.api.Tristate;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import me.lucko.luckperms.utils.Contexts;
import java.util.*;
@ -67,7 +68,7 @@ public class PermissionHolderLink implements PermissionHolder {
@Override
public Set<Node> getAllNodes() {
return Collections.unmodifiableSet(master.getAllNodes(null));
return Collections.unmodifiableSet(master.getAllNodes(Collections.emptyList(), Contexts.allowAll()));
}
@Override
@ -252,7 +253,7 @@ 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(server, world, extraContext, includeGlobal, applyGroups, possibleNodes);
return master.exportNodes(new Contexts(server, world, extraContext, includeGlobal, includeGlobal, applyGroups, true, true), possibleNodes);
}
@Override

View File

@ -28,6 +28,7 @@ import me.lucko.luckperms.commands.*;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.utils.Contexts;
import java.util.*;
@ -42,7 +43,7 @@ public class GroupChatMeta extends SubCommand<Group> {
SortedSet<Map.Entry<Integer, String>> prefixes = new TreeSet<>(Util.getMetaComparator().reversed());
SortedSet<Map.Entry<Integer, String>> suffixes = new TreeSet<>(Util.getMetaComparator().reversed());
for (Node node : group.getAllNodes(null)) {
for (Node node : group.getAllNodes(null, Contexts.allowAll())) {
if (!node.isSuffix() && !node.isPrefix()) {
continue;
}

View File

@ -49,6 +49,9 @@ public class InfoCommand extends SingleMainCommand {
c.getServer(),
c.getSyncTime(),
formatBoolean(c.getIncludeGlobalPerms()),
formatBoolean(c.getIncludeGlobalWorldPerms()),
formatBoolean(c.getApplyGlobalGroups()),
formatBoolean(c.getApplyGlobalWorldGroups()),
formatBoolean(c.getOnlineMode()),
formatBoolean(c.getApplyWildcards()),
formatBoolean(c.getApplyRegex()),

View File

@ -28,6 +28,7 @@ import me.lucko.luckperms.commands.*;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.users.User;
import me.lucko.luckperms.utils.Contexts;
import java.util.AbstractMap.SimpleEntry;
import java.util.List;
@ -46,7 +47,7 @@ public class UserChatMeta extends SubCommand<User> {
SortedSet<Map.Entry<Integer, String>> prefixes = new TreeSet<>(Util.getMetaComparator().reversed());
SortedSet<Map.Entry<Integer, String>> suffixes = new TreeSet<>(Util.getMetaComparator().reversed());
for (Node node : user.getAllNodes(null)) {
for (Node node : user.getAllNodes(null, Contexts.allowAll())) {
if (!node.isSuffix() && !node.isPrefix()) {
continue;
}

View File

@ -127,7 +127,10 @@ public enum Message {
PREFIX + "&f-> &eStorage Method: &6%s" + "\n" +
PREFIX + "&f-> &eServer Name: &6%s" + "\n" +
PREFIX + "&f-> &eSync Interval: &6%s minutes" + "\n" +
PREFIX + "&f-> &eInclude Global Perms: &6%s" + "\n" +
PREFIX + "&f-> &eInclude Global: &6%s" + "\n" +
PREFIX + "&f-> &eInclude Global World: &6%s" + "\n" +
PREFIX + "&f-> &eApply Global Groups: &6%s" + "\n" +
PREFIX + "&f-> &eApply Global World Groups: &6%s" + "\n" +
PREFIX + "&f-> &eOnline Mode: &6%s" + "\n" +
PREFIX + "&f-> &eApply Wildcards: &6%s" + "\n" +
PREFIX + "&f-> &eApply Regex: &6%s" + "\n" +

View File

@ -91,6 +91,18 @@ public abstract class LPConfiguration<T extends LuckPermsPlugin> {
return getBoolean("include-global", defaultIncludeGlobal);
}
public boolean getIncludeGlobalWorldPerms() {
return getBoolean("include-global-world", true);
}
public boolean getApplyGlobalGroups() {
return getBoolean("apply-global-groups", true);
}
public boolean getApplyGlobalWorldGroups() {
return getBoolean("apply-global-world-groups", true);
}
public boolean getOnlineMode() {
return getBoolean("online-mode", true);
}

View File

@ -36,6 +36,7 @@ import me.lucko.luckperms.api.implementation.internal.PermissionHolderLink;
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;
@ -143,7 +144,7 @@ public abstract class PermissionHolder {
* @param excludedGroups a list of groups to exclude
* @return a set of nodes
*/
public SortedSet<Node> getAllNodes(List<String> excludedGroups) {
public SortedSet<Node> getAllNodes(List<String> excludedGroups, Contexts context) {
SortedSet<Node> all = getPermissions(true);
if (excludedGroups == null) {
@ -152,13 +153,27 @@ public abstract class PermissionHolder {
excludedGroups.add(getObjectName().toLowerCase());
Set<String> parents = getPermissions(true).stream()
Set<Node> parents = getPermissions(true).stream()
.filter(Node::isGroupNode)
.map(Node::getGroupName)
.collect(Collectors.toSet());
for (String parent : parents) {
Group group = plugin.getGroupManager().get(parent);
Iterator<Node> iterator = parents.iterator();
while (iterator.hasNext()) {
Node node = iterator.next();
if (!node.shouldApplyOnServer(context.getServer(), context.isApplyGlobalGroups(), plugin.getConfiguration().getApplyRegex())) {
iterator.remove();
continue;
}
if (!node.shouldApplyOnWorld(context.getWorld(), context.isApplyGlobalWorldGroups(), plugin.getConfiguration().getApplyRegex())) {
iterator.remove();
continue;
}
}
for (Node parent : parents) {
Group group = plugin.getGroupManager().get(parent.getGroupName());
if (group == null) {
continue;
}
@ -168,7 +183,7 @@ public abstract class PermissionHolder {
}
inherited:
for (Node inherited : group.getAllNodes(excludedGroups)) {
for (Node inherited : group.getAllNodes(excludedGroups, context)) {
for (Node existing : all) {
if (existing.almostEquals(inherited)) {
continue inherited;
@ -184,34 +199,30 @@ public abstract class PermissionHolder {
/**
* Gets all of the nodes that this holder has (and inherits), given the context
* @param server the server
* @param world the world
* @param extraContext any extra context to filter by
* @param includeGlobal whether to include global nodes
* @param applyGroups if inherited group permissions should be included
* @param context the context for this request
* @return a map of permissions
*/
public Set<Node> getAllNodesFiltered(String server, String world, Map<String, String> extraContext, boolean includeGlobal, boolean applyGroups) {
public Set<Node> getAllNodesFiltered(Contexts context) {
Set<Node> perms = ConcurrentHashMap.newKeySet();
SortedSet<Node> allNodes;
if (applyGroups) {
allNodes = getAllNodes(null);
if (context.isApplyGroups()) {
allNodes = getAllNodes(null, context);
} else {
allNodes = getPermissions(true);
}
all:
for (Node node : allNodes) {
if (!node.shouldApplyOnServer(server, includeGlobal, plugin.getConfiguration().getApplyRegex())) {
if (!node.shouldApplyOnServer(context.getServer(), context.isIncludeGlobal(), plugin.getConfiguration().getApplyRegex())) {
continue;
}
if (!node.shouldApplyOnWorld(world, includeGlobal, plugin.getConfiguration().getApplyRegex())) {
if (!node.shouldApplyOnWorld(context.getWorld(), context.isIncludeGlobalWorld(), plugin.getConfiguration().getApplyRegex())) {
continue;
}
if (!node.shouldApplyWithContext(extraContext)) {
if (!node.shouldApplyWithContext(context.getExtraContext())) {
continue;
}
@ -229,19 +240,15 @@ public abstract class PermissionHolder {
}
/**
* Converts the output of {@link #getAllNodesFiltered(String, String, Map, boolean, boolean)}, and expands wildcards/regex/shorthand perms
* @param server the server
* @param world the world
* @param extraContext any extra context to filter by
* @param includeGlobal whether to include global nodes
* @param applyGroups if inherited group permissions should be included
* Converts the output of {@link #getAllNodesFiltered(Contexts)}, and expands wildcards/regex/shorthand perms
* @param context the context for this request
* @param possibleNodes a list of possible nodes for wildcards and regex permissions
* @return a map of permissions
*/
public Map<String, Boolean> exportNodes(String server, String world, Map<String, String> extraContext, boolean includeGlobal, boolean applyGroups, List<String> possibleNodes) {
public Map<String, Boolean> exportNodes(Contexts context, List<String> possibleNodes) {
Map<String, Boolean> perms = new HashMap<>();
for (Node node : getAllNodesFiltered(server, world, extraContext, includeGlobal, applyGroups)) {
for (Node node : getAllNodesFiltered(context)) {
if (node.getPermission().equals("*") || node.getPermission().equals("'*'")) {
if (possibleNodes != null && plugin.getConfiguration().getApplyWildcards()) {
possibleNodes.forEach(n -> perms.put(n, true));
@ -356,7 +363,7 @@ public abstract class PermissionHolder {
* @return a tristate
*/
public Tristate inheritsPermission(Node node) {
return hasPermission(getAllNodes(null), node);
return hasPermission(getAllNodes(null, Contexts.allowAll()), node);
}
public boolean inheritsPermission(String node, boolean b) {
@ -539,18 +546,24 @@ public abstract class PermissionHolder {
/*
* Don't use these methods, only here for compat reasons
*/
@Deprecated
public Map<String, Boolean> getLocalPermissions(String server, String world, List<String> excludedGroups, List<String> possibleNodes) {
return exportNodes(server, world, null, plugin.getConfiguration().getIncludeGlobalPerms(), true, possibleNodes);
return exportNodes(new Contexts(server, world, Collections.emptyMap(), plugin.getConfiguration().getIncludeGlobalPerms(), true, true, true, true), Collections.emptyList());
}
@Deprecated
public Map<String, Boolean> getLocalPermissions(String server, String world, List<String> excludedGroups) {
return exportNodes(server, world, null, plugin.getConfiguration().getIncludeGlobalPerms(), true, null);
return exportNodes(new Contexts(server, world, Collections.emptyMap(), plugin.getConfiguration().getIncludeGlobalPerms(), true, true, true, true), Collections.emptyList());
}
@SuppressWarnings("deprecation")
@Deprecated
public Map<String, Boolean> getLocalPermissions(String server, List<String> excludedGroups, List<String> possibleNodes) {
return getLocalPermissions(server, null, excludedGroups, possibleNodes);
}
@SuppressWarnings("deprecation")
@Deprecated
public Map<String, Boolean> getLocalPermissions(String server, List<String> excludedGroups) {
return getLocalPermissions(server, null, excludedGroups, null);
}

View File

@ -0,0 +1,61 @@
/*
* 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.utils;
import lombok.AllArgsConstructor;
import lombok.Getter;
import me.lucko.luckperms.core.LPConfiguration;
import java.util.Collections;
import java.util.Map;
@Getter
@AllArgsConstructor
public class Contexts {
public static Contexts fromConfig(LPConfiguration configuration) {
return new Contexts(
configuration.getServer(),
null,
Collections.emptyMap(),
configuration.getIncludeGlobalPerms(),
configuration.getIncludeGlobalWorldPerms(),
true,
configuration.getApplyGlobalGroups(),
configuration.getApplyGlobalWorldGroups()
);
}
public static Contexts allowAll() {
return new Contexts(null, null, Collections.emptyMap(), true, true, true, true, true);
}
private final String server;
private final String world;
private final Map<String, String> extraContext;
private final boolean includeGlobal;
private final boolean includeGlobalWorld;
private final boolean applyGroups;
private final boolean applyGlobalGroups;
private final boolean applyGlobalWorldGroups;
}

View File

@ -35,6 +35,7 @@ import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.users.User;
import me.lucko.luckperms.utils.Contexts;
import org.spongepowered.api.command.CommandSource;
import org.spongepowered.api.service.context.Context;
import org.spongepowered.api.service.permission.Subject;
@ -203,7 +204,7 @@ public class LuckPermsSubject implements Subject {
int priority = Integer.MIN_VALUE;
String meta = null;
for (Node n : holder.getAllNodes(null)) {
for (Node n : holder.getAllNodes(null, Contexts.allowAll())) {
if (!n.getValue()) {
continue;
}
@ -343,7 +344,7 @@ public class LuckPermsSubject implements Subject {
public Map<Set<Context>, List<Subject>> getAllParents() {
Map<Set<Context>, List<Subject>> parents = new HashMap<>();
for (Node n : holder.getAllNodes(null)) {
for (Node n : holder.getAllNodes(null, Contexts.allowAll())) {
if (!n.isGroupNode()) {
continue;
}
@ -470,7 +471,7 @@ public class LuckPermsSubject implements Subject {
public Map<Set<Context>, Map<String, String>> getAllOptions() {
Map<Set<Context>, Map<String, String>> options = new HashMap<>();
for (Node n : holder.getAllNodes(null)) {
for (Node n : holder.getAllNodes(null, Contexts.allowAll())) {
if (!n.isMeta()) {
continue;
}

View File

@ -27,6 +27,7 @@ import me.lucko.luckperms.api.event.events.UserPermissionRefreshEvent;
import me.lucko.luckperms.api.implementation.internal.UserLink;
import me.lucko.luckperms.api.sponge.LuckPermsUserSubject;
import me.lucko.luckperms.api.sponge.collections.UserCollection;
import me.lucko.luckperms.utils.Contexts;
import java.util.Collections;
import java.util.Map;
@ -46,7 +47,7 @@ class SpongeUser extends User {
}
@Override
public void refreshPermissions() {
public synchronized void refreshPermissions() {
UserCollection uc = plugin.getService().getUserSubjects();
if (!uc.getUsers().containsKey(getUuid())) {
return;
@ -54,11 +55,16 @@ class SpongeUser extends User {
// Calculate the permissions that should be applied. This is done async, who cares about how long it takes or how often it's done.
Map<String, Boolean> toApply = exportNodes(
getPlugin().getConfiguration().getServer(),
null, // TODO per world perms
null,
plugin.getConfiguration().getIncludeGlobalPerms(),
true,
new Contexts(
plugin.getConfiguration().getServer(),
null, // TODO per world perms
null,
plugin.getConfiguration().getIncludeGlobalPerms(),
plugin.getConfiguration().getIncludeGlobalWorldPerms(),
true,
plugin.getConfiguration().getApplyGlobalGroups(),
plugin.getConfiguration().getApplyGlobalWorldGroups()
),
Collections.emptyList()
);

View File

@ -8,9 +8,20 @@
# The name of the server, used for server specific permissions. Set to 'global' to disable.
server="global"
# If users on this server should have their global permissions/groups applied.
# If users on this server should have their global permissions applied.
# If set to false, only server specific permissions will apply for users on this server
include-global=true
# If users on this server should have their global world permissions applied.
# If set to false, only world specific permissions will apply for users on this server
include-global-world=true
# If users on this server should have global (non-server specific) groups applied
apply-global-groups=true
# If users on this server should have global (non-world specific) groups applied
apply-global-world-groups=true
# If this server is in offline or online mode.
# This setting allows a player to have the same UUID across a network of offline mode/mixed servers.