Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fa9324bda8 | ||
|
|
1e72f9d8fe | ||
|
|
50fd954599 | ||
|
|
b1e34b55f8 | ||
|
|
cff1b8a411 | ||
|
|
6ffa6720be | ||
|
|
f52a106165 | ||
|
|
bf247b71e1 | ||
|
|
66818e4c82 | ||
|
|
23d53d39b4 | ||
|
|
30ea5a5b69 | ||
|
|
e7a210dc06 | ||
|
|
497de9824a | ||
|
|
be74b50762 | ||
|
|
f2e06b56e7 | ||
|
|
f6aa20c300 | ||
|
|
5e16134f6f | ||
|
|
6165fcbb21 | ||
|
|
831e882db0 | ||
|
|
feb8bf4bd3 | ||
|
|
ce3ee866ca | ||
|
|
d29dd35689 | ||
|
|
3a0a89853f | ||
|
|
e7ca79d251 | ||
|
|
22426bab33 | ||
|
|
116094ea96 | ||
|
|
9df39a9545 | ||
|
|
b8f44df723 | ||
|
|
74f275eb69 | ||
|
|
1142cbcb2c | ||
|
|
37749e5829 | ||
|
|
f9025c7a51 | ||
|
|
c7bfc38477 | ||
|
|
7ca394d7b9 | ||
|
|
31884ea59d | ||
|
|
e79b7c7023 | ||
|
|
1fdb4e8ade | ||
|
|
53db8c5928 | ||
|
|
07514000a4 | ||
|
|
f28721e55a | ||
|
|
fc230291d3 | ||
|
|
89ff4cfa40 | ||
|
|
d786b6abb2 | ||
|
|
fb0e694155 | ||
|
|
cd6cac1fb6 |
No files matched your search
@@ -1,5 +1,6 @@
|
||||

|
||||
# LuckPerms [](https://ci.lucko.me/job/LuckPerms/)
|
||||
A permissions implementation for Bukkit/Spigot, BungeeCord and Sponge.
|
||||
An advanced permissions implementation for Bukkit/Spigot, BungeeCord and Sponge.
|
||||
|
||||
## Links
|
||||
* **Development Builds** - <https://ci.lucko.me/job/LuckPerms>
|
||||
@@ -9,9 +10,17 @@ A permissions implementation for Bukkit/Spigot, BungeeCord and Sponge.
|
||||
## Description
|
||||
LuckPerms is an advanced permissions implementation aiming to be a flexible, performant and reliable alternative to other permission systems, providing all the features you could ever possibly need in a permissions plugin, along with an extensive and well documented API for developers.
|
||||
|
||||
* [Spigot Plugin Page](https://www.spigotmc.org/resources/luckperms-an-advanced-permissions-system.28140/ "Spigot Plugin Page")
|
||||
* [Sponge Plugin Page](https://forums.spongepowered.org/t/luckperms-an-advanced-permissions-system/14274 "Sponge Plugin Page")
|
||||
|
||||
## LuckPerms vs Other Plugins
|
||||

|
||||
_Features checked on 23rd Aug 2016. If you find any inaccuracies, please do let me know. I tried to be as fair as possible, and copy all major features from the respective plugin pages._
|
||||
|
||||
## License
|
||||
See LICENSE.md.
|
||||
|
||||
## Thanks to:
|
||||
[](http://www.ej-technologies.com/products/jprofiler/overview.html)
|
||||
|
||||
Thanks to ej-technologies for granting LuckPerms an open source licence to their [java profiling software](http://www.ej-technologies.com/products/jprofiler/overview.html "Java Profiler").
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luckperms</artifactId>
|
||||
<groupId>me.lucko.luckperms</groupId>
|
||||
<version>2.8-SNAPSHOT</version>
|
||||
<version>2.9-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -62,6 +62,24 @@ public interface LPConfiguration {
|
||||
*/
|
||||
boolean getIncludeGlobalPerms();
|
||||
|
||||
/**
|
||||
* @return if the users on this server will have their global world permissions applied
|
||||
* @since 2.9
|
||||
*/
|
||||
boolean getIncludeGlobalWorldPerms();
|
||||
|
||||
/**
|
||||
* @return true if the platform is applying global groups
|
||||
* @since 2.9
|
||||
*/
|
||||
boolean getApplyGlobalGroups();
|
||||
|
||||
/**
|
||||
* @return true if the platform is applying global world groups
|
||||
* @since 2.9
|
||||
*/
|
||||
boolean getApplyGlobalWorldGroups();
|
||||
|
||||
/**
|
||||
* @return the online mode setting in the config
|
||||
*/
|
||||
@@ -88,6 +106,12 @@ public interface LPConfiguration {
|
||||
*/
|
||||
boolean getLogNotify();
|
||||
|
||||
/**
|
||||
* @return true if permission checks are being recorded / debugged
|
||||
* @since 2.9
|
||||
*/
|
||||
boolean getDebugPermissionChecks();
|
||||
|
||||
/**
|
||||
* @return true if the vanilla op system is enabled
|
||||
* @since 2.8
|
||||
@@ -100,6 +124,12 @@ public interface LPConfiguration {
|
||||
*/
|
||||
boolean getCommandsAllowOp();
|
||||
|
||||
/**
|
||||
* @return true if auto op is enabled
|
||||
* @since 2.9
|
||||
*/
|
||||
boolean getAutoOp();
|
||||
|
||||
/**
|
||||
* @return the name of the server used within Vault operations
|
||||
* @since 2.7
|
||||
|
||||
@@ -187,7 +187,7 @@ public interface LuckPermsApi {
|
||||
Track getTrack(String name);
|
||||
|
||||
/**
|
||||
* Gets a wrapped tracj object from the track storage. This method does not return null, unlike {@link #getTrack}
|
||||
* Gets a wrapped track object from the track storage. This method does not return null, unlike {@link #getTrack}
|
||||
* @param name the name of the track to get
|
||||
* @return an optional {@link Track} object
|
||||
* @throws NullPointerException if the name is null
|
||||
|
||||
@@ -30,7 +30,12 @@ public enum PlatformType {
|
||||
|
||||
BUKKIT("Bukkit"),
|
||||
BUNGEE("Bungee"),
|
||||
SPONGE("Sponge");
|
||||
SPONGE("Sponge"),
|
||||
|
||||
/**
|
||||
* @since 2.9
|
||||
*/
|
||||
STANDALONE("Standalone");
|
||||
|
||||
private final String friendlyName;
|
||||
|
||||
|
||||
@@ -1,3 +1,25 @@
|
||||
/*
|
||||
* 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.exceptions;
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>luckperms</artifactId>
|
||||
<groupId>me.lucko.luckperms</groupId>
|
||||
<version>2.9-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>luckperms-bukkit-legacy</artifactId>
|
||||
<build>
|
||||
<defaultGoal>clean package</defaultGoal>
|
||||
<finalName>LuckPerms-bukkit-legacy-${release.version}.${git.closest.tag.commit.count}</finalName>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.5.1</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>2.4.3</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<minimizeJar>false</minimizeJar>
|
||||
<artifactSet>
|
||||
<excludes>
|
||||
<exclude>org.xerial:*</exclude>
|
||||
</excludes>
|
||||
</artifactSet>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>org.slf4j</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.slf4j</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.zaxxer.hikari</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.hikari</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.mongodb</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.mongodb</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.bson</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.bson</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.h2</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.h2</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>pl.project13.maven</groupId>
|
||||
<artifactId>git-commit-id-plugin</artifactId>
|
||||
<version>2.2.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>revision</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<injectAllReactorProjects>true</injectAllReactorProjects>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<!-- LuckPerms Bukkit -->
|
||||
<dependency>
|
||||
<groupId>me.lucko.luckperms</groupId>
|
||||
<artifactId>luckperms-bukkit</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Shade gson and guava, as they are not included in earlier Bukkit releases -->
|
||||
<!-- gson -->
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.7</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<!-- guava -->
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>19.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luckperms</artifactId>
|
||||
<groupId>me.lucko.luckperms</groupId>
|
||||
<version>2.8-SNAPSHOT</version>
|
||||
<version>2.9-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -30,8 +30,8 @@
|
||||
<dependency>
|
||||
<groupId>me.lucko.luckperms</groupId>
|
||||
<artifactId>luckperms-api</artifactId>
|
||||
<version>2.5</version>
|
||||
<scope>compile</scope>
|
||||
<version>2.8</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- BukkitAPI -->
|
||||
<dependency>
|
||||
|
||||
+13
-78
@@ -25,15 +25,11 @@ package me.lucko.luckperms.api.placeholders;
|
||||
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||
import me.clip.placeholderapi.util.TimeUtil;
|
||||
import me.lucko.luckperms.api.LuckPermsApi;
|
||||
import me.lucko.luckperms.api.Track;
|
||||
import me.lucko.luckperms.api.User;
|
||||
import me.lucko.luckperms.api.*;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/*
|
||||
* PlaceholderAPI Expansion for LuckPerms, implemented using the LuckPerms API.
|
||||
@@ -75,7 +71,7 @@ public class LuckPermsPlaceholderExpansion extends PlaceholderExpansion {
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return "2.5";
|
||||
return "2.8";
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -84,7 +80,7 @@ public class LuckPermsPlaceholderExpansion extends PlaceholderExpansion {
|
||||
return "";
|
||||
}
|
||||
|
||||
Optional<User> u = api.getUserSafe(player.getUniqueId());
|
||||
Optional<User> u = api.getUserSafe(api.getUuidCache().getUUID(player.getUniqueId()));
|
||||
if (!u.isPresent()) {
|
||||
return "";
|
||||
}
|
||||
@@ -127,17 +123,11 @@ public class LuckPermsPlaceholderExpansion extends PlaceholderExpansion {
|
||||
|
||||
if (identifier.startsWith("expiry_time_") && identifier.length() > "expiry_time_".length()) {
|
||||
String node = identifier.substring("expiry_time_".length());
|
||||
|
||||
|
||||
long currentTime = System.currentTimeMillis() / 1000L;
|
||||
Map<Map.Entry<String, Boolean>, Long> temps = user.getTemporaryNodes();
|
||||
|
||||
for (Map.Entry<Map.Entry<String, Boolean>, Long> e : temps.entrySet()) {
|
||||
if (!e.getKey().getKey().equalsIgnoreCase(node)) {
|
||||
continue;
|
||||
for (Node n : user.getTemporaryPermissionNodes()) {
|
||||
if (n.getPermission().equalsIgnoreCase(node)) {
|
||||
return TimeUtil.getTime((int) (n.getExpiryUnixTime() - currentTime));
|
||||
}
|
||||
|
||||
return TimeUtil.getTime((int) (e.getValue() - currentTime));
|
||||
}
|
||||
|
||||
return "";
|
||||
@@ -145,42 +135,27 @@ public class LuckPermsPlaceholderExpansion extends PlaceholderExpansion {
|
||||
|
||||
if (identifier.startsWith("group_expiry_time_") && identifier.length() > "group_expiry_time_".length()) {
|
||||
String node = "group." + identifier.substring("group_expiry_time_".length());
|
||||
|
||||
long currentTime = System.currentTimeMillis() / 1000L;
|
||||
Map<Map.Entry<String, Boolean>, Long> temps = user.getTemporaryNodes();
|
||||
|
||||
for (Map.Entry<Map.Entry<String, Boolean>, Long> e : temps.entrySet()) {
|
||||
if (!e.getKey().getKey().equalsIgnoreCase(node)) {
|
||||
continue;
|
||||
for (Node n : user.getTemporaryPermissionNodes()) {
|
||||
if (n.getPermission().equalsIgnoreCase(node)) {
|
||||
return TimeUtil.getTime((int) (n.getExpiryUnixTime() - currentTime));
|
||||
}
|
||||
|
||||
return TimeUtil.getTime((int) (e.getValue() - currentTime));
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
if (identifier.equalsIgnoreCase("prefix")) {
|
||||
return getChatMeta(PREFIX_PATTERN, user);
|
||||
return MetaUtils.getPrefix(user, null, null, true);
|
||||
}
|
||||
|
||||
if (identifier.equalsIgnoreCase("suffix")) {
|
||||
return getChatMeta(SUFFIX_PATTERN, user);
|
||||
return MetaUtils.getSuffix(user, null, null, true);
|
||||
}
|
||||
|
||||
if (identifier.startsWith("meta_") && identifier.length() > "meta_".length()) {
|
||||
String node = "meta." + escapeCharacters(identifier.substring("meta_".length())) + ".";
|
||||
Map<String, Boolean> nodes = user.getNodes();
|
||||
|
||||
for (Map.Entry<String, Boolean> e : nodes.entrySet()) {
|
||||
if (!e.getValue()) continue;
|
||||
if (!e.getKey().toLowerCase().startsWith(node)) continue;
|
||||
|
||||
String meta = e.getKey().substring(node.length());
|
||||
return unescapeCharacters(meta);
|
||||
}
|
||||
|
||||
return "";
|
||||
String node = identifier.substring("meta_".length());
|
||||
return MetaUtils.getMeta(user, null, null, node, "", true);
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -204,44 +179,4 @@ public class LuckPermsPlaceholderExpansion extends PlaceholderExpansion {
|
||||
private static String formatBoolean(boolean b) {
|
||||
return b ? PlaceholderAPIPlugin.booleanTrue() : PlaceholderAPIPlugin.booleanFalse();
|
||||
}
|
||||
|
||||
private static String escapeCharacters(String s) {
|
||||
s = s.replace(".", "{SEP}");
|
||||
s = s.replace("/", "{FSEP}");
|
||||
s = s.replace("$", "{DSEP}");
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
private static String unescapeCharacters(String s) {
|
||||
s = s.replace("{SEP}", ".");
|
||||
s = s.replace("{FSEP}", "/");
|
||||
s = s.replace("{DSEP}", "$");
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
private static final Pattern PREFIX_PATTERN = Pattern.compile("(?i)prefix\\.\\d+\\..*");
|
||||
private static final Pattern SUFFIX_PATTERN = Pattern.compile("(?i)suffix\\.\\d+\\..*");
|
||||
private static final Pattern DOT_PATTERN = Pattern.compile("\\.");
|
||||
|
||||
private static String getChatMeta(Pattern pattern, User user) {
|
||||
int priority = 0;
|
||||
String meta = null;
|
||||
for (Map.Entry<String, Boolean> e : user.getLocalPermissions(null, null).entrySet()) {
|
||||
if (!e.getValue()) continue;
|
||||
|
||||
if (pattern.matcher(e.getKey()).matches()) {
|
||||
String[] parts = DOT_PATTERN.split(e.getKey(), 3);
|
||||
int p = Integer.parseInt(parts[1]);
|
||||
|
||||
if (meta == null || p > priority) {
|
||||
meta = parts[2];
|
||||
priority = p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return meta == null ? "" : unescapeCharacters(meta);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luckperms</artifactId>
|
||||
<groupId>me.lucko.luckperms</groupId>
|
||||
<version>2.8-SNAPSHOT</version>
|
||||
<version>2.9-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -22,8 +22,12 @@
|
||||
|
||||
package me.lucko.luckperms;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Splitter;
|
||||
import me.lucko.luckperms.api.data.Callback;
|
||||
import me.lucko.luckperms.commands.CommandManager;
|
||||
import me.lucko.luckperms.commands.Util;
|
||||
import me.lucko.luckperms.constants.Patterns;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
@@ -39,7 +43,12 @@ class BukkitCommand extends CommandManager implements CommandExecutor, TabExecut
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
onCommand(BukkitSenderFactory.get().wrap(sender), label, Arrays.asList(args), Callback.empty());
|
||||
onCommand(
|
||||
BukkitSenderFactory.get().wrap(sender),
|
||||
label,
|
||||
Util.stripQuotes(Splitter.on(Patterns.COMMAND_SEPARATOR).omitEmptyStrings().splitToList(Joiner.on(' ').join(args))),
|
||||
Callback.empty()
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,17 +23,18 @@
|
||||
package me.lucko.luckperms;
|
||||
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.inject.Injector;
|
||||
import me.lucko.luckperms.inject.LPPermissible;
|
||||
import me.lucko.luckperms.users.BukkitUser;
|
||||
import me.lucko.luckperms.users.User;
|
||||
import me.lucko.luckperms.utils.AbstractListener;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.*;
|
||||
import org.bukkit.permissions.PermissionAttachment;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.UUID;
|
||||
|
||||
class BukkitListener extends AbstractListener implements Listener {
|
||||
private final LPBukkitPlugin plugin;
|
||||
@@ -43,7 +44,7 @@ class BukkitListener extends AbstractListener implements Listener {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onPlayerPreLogin(AsyncPlayerPreLoginEvent e) {
|
||||
if (!plugin.getDatastore().isAcceptingLogins()) {
|
||||
// The datastore is disabled, prevent players from joining the server
|
||||
@@ -54,7 +55,7 @@ class BukkitListener extends AbstractListener implements Listener {
|
||||
onAsyncLogin(e.getUniqueId(), e.getName());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onPlayerLogin(PlayerLoginEvent e) {
|
||||
final Player player = e.getPlayer();
|
||||
final User user = plugin.getUserManager().get(plugin.getUuidCache().getUUID(player.getUniqueId()));
|
||||
@@ -67,42 +68,37 @@ class BukkitListener extends AbstractListener implements Listener {
|
||||
if (user instanceof BukkitUser) {
|
||||
BukkitUser u = (BukkitUser) user;
|
||||
|
||||
PermissionAttachment attachment = player.addAttachment(plugin);
|
||||
Map<String, Boolean> newPermMap = new ConcurrentHashMap<>();
|
||||
try {
|
||||
/* Replace the standard LinkedHashMap in the attachment with a ConcurrentHashMap.
|
||||
This means that we can iterate over and change the permissions within our attachment asynchronously,
|
||||
without worrying about thread safety. The Bukkit side of things should still operate normally. Internal
|
||||
permission stuff should work the same. This is by far the most easy and efficient way to do things, without
|
||||
having to do tons of reflection. */
|
||||
BukkitUser.getPermissionsField().set(attachment, newPermMap);
|
||||
LPPermissible lpPermissible = new LPPermissible(player, plugin);
|
||||
Injector.inject(player, lpPermissible);
|
||||
u.setLpPermissible(lpPermissible);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
|
||||
u.setAttachment(new BukkitUser.PermissionAttachmentHolder(attachment, newPermMap));
|
||||
}
|
||||
|
||||
plugin.doAsync(user::refreshPermissions);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onPlayerJoin(PlayerJoinEvent e) {
|
||||
// Refresh permissions again
|
||||
plugin.getUserManager().getWorldCache().put(e.getPlayer().getUniqueId(), e.getPlayer().getWorld().getName());
|
||||
plugin.doAsync(() -> refreshPlayer(e.getPlayer().getUniqueId()));
|
||||
UUID internal = plugin.getUuidCache().getUUID(e.getPlayer().getUniqueId());
|
||||
plugin.getUserManager().getWorldCache().put(internal, e.getPlayer().getWorld().getName());
|
||||
plugin.doAsync(() -> refreshPlayer(internal));
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onPlayerChangedWorld(PlayerChangedWorldEvent e) {
|
||||
plugin.getUserManager().getWorldCache().put(e.getPlayer().getUniqueId(), e.getPlayer().getWorld().getName());
|
||||
plugin.doAsync(() -> refreshPlayer(e.getPlayer().getUniqueId()));
|
||||
UUID internal = plugin.getUuidCache().getUUID(e.getPlayer().getUniqueId());
|
||||
plugin.getUserManager().getWorldCache().put(internal, e.getPlayer().getWorld().getName());
|
||||
plugin.doAsync(() -> refreshPlayer(internal));
|
||||
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onPlayerQuit(PlayerQuitEvent e) {
|
||||
plugin.getUserManager().getWorldCache().remove(e.getPlayer().getUniqueId());
|
||||
plugin.getUserManager().getWorldCache().remove(plugin.getUuidCache().getUUID(e.getPlayer().getUniqueId()));
|
||||
onLeave(e.getPlayer().getUniqueId());
|
||||
}
|
||||
|
||||
|
||||
@@ -34,8 +34,8 @@ import java.util.UUID;
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class BukkitSenderFactory extends SenderFactory<CommandSender> {
|
||||
private static BukkitSenderFactory instance = null;
|
||||
public static BukkitSenderFactory get() {
|
||||
if (instance == null){
|
||||
public static synchronized BukkitSenderFactory get() {
|
||||
if (instance == null) {
|
||||
instance = new BukkitSenderFactory();
|
||||
}
|
||||
return instance;
|
||||
|
||||
@@ -194,8 +194,11 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Sender> getSenders() {
|
||||
return getServer().getOnlinePlayers().stream().map(p -> BukkitSenderFactory.get().wrap(p)).collect(Collectors.toList());
|
||||
public List<Sender> getNotifyListeners() {
|
||||
return getServer().getOnlinePlayers().stream()
|
||||
.map(p -> BukkitSenderFactory.get().wrap(p, Collections.singleton(me.lucko.luckperms.constants.Permission.LOG_NOTIFY)))
|
||||
.filter(me.lucko.luckperms.constants.Permission.LOG_NOTIFY::isAuthorized)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -267,11 +270,11 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
||||
"luckperms." + e.getKey() + ".*", def,
|
||||
e.getValue().stream()
|
||||
.map(tag -> "luckperms." + e.getKey() + "." + tag)
|
||||
.collect(Collectors.toMap(s -> s, s -> false))
|
||||
.collect(Collectors.toMap(s -> s, s -> true))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
pm.addPermission(new Permission("luckperms.*", def, all.stream().collect(Collectors.toMap(s -> s, s -> false))));
|
||||
pm.addPermission(new Permission("luckperms.*", def, all.stream().collect(Collectors.toMap(s -> s, s -> true))));
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
@@ -118,10 +119,8 @@ public class VaultChatHook extends Chat {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!perms.getServer().equalsIgnoreCase("global")) {
|
||||
if (!n.shouldApplyOnServer(perms.getServer(), perms.isIncludeGlobal(), false)) {
|
||||
continue;
|
||||
}
|
||||
if (!n.shouldApplyOnServer(perms.getServer(), perms.isIncludeGlobal(), false)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!n.shouldApplyOnWorld(world, perms.isIncludeGlobal(), false)) {
|
||||
@@ -164,22 +163,20 @@ 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;
|
||||
}
|
||||
|
||||
if (!perms.getServer().equalsIgnoreCase("global")) {
|
||||
if (!n.shouldApplyOnServer(perms.getServer(), perms.isIncludeGlobal(), false)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!n.shouldApplyOnWorld(world, perms.isIncludeGlobal(), false)) {
|
||||
if (prefix ? !n.isPrefix() : !n.isSuffix()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (prefix ? !n.isPrefix() : !n.isSuffix()) {
|
||||
if (!n.shouldApplyOnServer(perms.getServer(), perms.isIncludeGlobal(), false)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!n.shouldApplyOnWorld(world, perms.isIncludeGlobal(), false)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* 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.inject;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.permissions.Permissible;
|
||||
import org.bukkit.permissions.PermissibleBase;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* Injects a {@link LPPermissible} into a {@link Player}
|
||||
*/
|
||||
@UtilityClass
|
||||
public class Injector {
|
||||
private static Field HUMAN_ENTITY_FIELD;
|
||||
|
||||
static {
|
||||
try {
|
||||
HUMAN_ENTITY_FIELD = Class.forName(getInternalClassName("entity.CraftHumanEntity")).getDeclaredField("perm");
|
||||
HUMAN_ENTITY_FIELD.setAccessible(true);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean inject(CommandSender sender, PermissibleBase permissible) {
|
||||
try {
|
||||
Field f = getPermField(sender);
|
||||
f.set(sender, permissible);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean unInject(CommandSender sender) {
|
||||
try {
|
||||
Permissible permissible = getPermissible(sender);
|
||||
if (permissible instanceof LPPermissible) {
|
||||
getPermField(sender).set(sender, new PermissibleBase(sender));
|
||||
}
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static Permissible getPermissible(CommandSender sender) {
|
||||
try {
|
||||
Field f = getPermField(sender);
|
||||
return (Permissible) f.get(sender);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static Field getPermField(CommandSender sender) {
|
||||
if (sender instanceof Player) {
|
||||
return HUMAN_ENTITY_FIELD;
|
||||
}
|
||||
throw new RuntimeException("Couldn't get perm field for sender " + sender.getClass().getName());
|
||||
}
|
||||
|
||||
private static String getInternalClassName(String className) {
|
||||
Class server = Bukkit.getServer().getClass();
|
||||
if (!server.getSimpleName().equals("CraftServer")) {
|
||||
throw new RuntimeException("Couldn't inject into server " + server);
|
||||
}
|
||||
|
||||
String version;
|
||||
if (server.getName().equals("org.bukkit.craftbukkit.CraftServer")) {
|
||||
// Non versioned class
|
||||
version = ".";
|
||||
} else {
|
||||
version = server.getName().substring("org.bukkit.craftbukkit".length());
|
||||
version = version.substring(0, version.length() - "CraftServer".length());
|
||||
}
|
||||
|
||||
return "org.bukkit.craftbukkit" + version + className;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,303 @@
|
||||
/*
|
||||
* 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.inject;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.api.Tristate;
|
||||
import me.lucko.luckperms.utils.PermissionCalculator;
|
||||
import me.lucko.luckperms.utils.PermissionProcessor;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.permissions.*;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Modified PermissibleBase for LuckPerms
|
||||
*/
|
||||
public class LPPermissible extends PermissibleBase {
|
||||
|
||||
@Getter
|
||||
private final CommandSender parent;
|
||||
|
||||
private final PermissionCalculator calculator;
|
||||
|
||||
@Getter
|
||||
private final Map<String, Boolean> luckPermsPermissions = new ConcurrentHashMap<>();
|
||||
private final List<PermissionAttachment> attachments = new LinkedList<>();
|
||||
private final Map<String, PermissionAttachmentInfo> attachmentPermissions = new HashMap<>();
|
||||
|
||||
public LPPermissible(@NonNull CommandSender sender, LuckPermsPlugin plugin) {
|
||||
super(sender);
|
||||
this.parent = sender;
|
||||
|
||||
List<PermissionProcessor> processors = new ArrayList<>(5);
|
||||
processors.add(new PermissionCalculator.MapProcessor(luckPermsPermissions));
|
||||
processors.add(new AttachmentProcessor(attachmentPermissions));
|
||||
if (plugin.getConfiguration().getApplyWildcards()) {
|
||||
processors.add(new PermissionCalculator.WildcardProcessor(luckPermsPermissions));
|
||||
}
|
||||
if (plugin.getConfiguration().getApplyRegex()) {
|
||||
processors.add(new PermissionCalculator.RegexProcessor(luckPermsPermissions));
|
||||
}
|
||||
processors.add(new BukkitDefaultsProcessor(parent::isOp));
|
||||
|
||||
calculator = new PermissionCalculator(plugin, parent.getName(), plugin.getConfiguration().getDebugPermissionChecks(), processors);
|
||||
}
|
||||
|
||||
public void invalidateCache() {
|
||||
calculator.invalidateCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOp() {
|
||||
return parent.isOp();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOp(boolean value) {
|
||||
parent.setOp(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPermissionSet(@NonNull String name) {
|
||||
return luckPermsPermissions.containsKey(name.toLowerCase()) || attachmentPermissions.containsKey(name.toLowerCase());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPermissionSet(@NonNull Permission perm) {
|
||||
return isPermissionSet(perm.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(@NonNull String name) {
|
||||
Tristate ts = calculator.getPermissionValue(name);
|
||||
if (ts != Tristate.UNDEFINED) {
|
||||
return ts.asBoolean();
|
||||
}
|
||||
|
||||
return Permission.DEFAULT_PERMISSION.getValue(isOp());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(@NonNull Permission perm) {
|
||||
Tristate ts = calculator.getPermissionValue(perm.getName());
|
||||
if (ts != Tristate.UNDEFINED) {
|
||||
return ts.asBoolean();
|
||||
}
|
||||
|
||||
return perm.getDefault().getValue(isOp());
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionAttachment addAttachment(@NonNull Plugin plugin, @NonNull String name, boolean value) {
|
||||
if (!plugin.isEnabled()) {
|
||||
throw new IllegalArgumentException("Plugin " + plugin.getDescription().getFullName() + " is not enabled");
|
||||
}
|
||||
|
||||
PermissionAttachment result = addAttachment(plugin);
|
||||
result.setPermission(name, value);
|
||||
|
||||
recalculatePermissions();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionAttachment addAttachment(@NonNull Plugin plugin) {
|
||||
if (!plugin.isEnabled()) {
|
||||
throw new IllegalArgumentException("Plugin " + plugin.getDescription().getFullName() + " is not enabled");
|
||||
}
|
||||
|
||||
PermissionAttachment result = new PermissionAttachment(plugin, parent);
|
||||
|
||||
attachments.add(result);
|
||||
recalculatePermissions();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionAttachment addAttachment(@NonNull Plugin plugin, @NonNull String name, boolean value, int ticks) {
|
||||
if (!plugin.isEnabled()) {
|
||||
throw new IllegalArgumentException("Plugin " + plugin.getDescription().getFullName() + " is not enabled");
|
||||
}
|
||||
|
||||
PermissionAttachment result = addAttachment(plugin, ticks);
|
||||
if (result != null) {
|
||||
result.setPermission(name, value);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionAttachment addAttachment(@NonNull Plugin plugin, int ticks) {
|
||||
if (!plugin.isEnabled()) {
|
||||
throw new IllegalArgumentException("Plugin " + plugin.getDescription().getFullName() + " is not enabled");
|
||||
}
|
||||
|
||||
PermissionAttachment result = addAttachment(plugin);
|
||||
if (Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new RemoveAttachmentRunnable(result), ticks) == -1) {
|
||||
Bukkit.getServer().getLogger().log(Level.WARNING, "Could not add PermissionAttachment to " + parent + " for plugin " + plugin.getDescription().getFullName() + ": Scheduler returned -1");
|
||||
result.remove();
|
||||
return null;
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAttachment(@NonNull PermissionAttachment attachment) {
|
||||
if (attachments.contains(attachment)) {
|
||||
attachments.remove(attachment);
|
||||
PermissionRemovedExecutor ex = attachment.getRemovalCallback();
|
||||
|
||||
if (ex != null) {
|
||||
ex.attachmentRemoved(attachment);
|
||||
}
|
||||
|
||||
recalculatePermissions();
|
||||
} else {
|
||||
throw new IllegalArgumentException("Given attachment is not part of Permissible object " + parent);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recalculatePermissions() {
|
||||
if (attachmentPermissions == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
attachmentPermissions.clear();
|
||||
Set<Permission> defaults = Bukkit.getServer().getPluginManager().getDefaultPermissions(isOp());
|
||||
Bukkit.getServer().getPluginManager().subscribeToDefaultPerms(isOp(), parent);
|
||||
|
||||
for (Permission perm : defaults) {
|
||||
String name = perm.getName().toLowerCase();
|
||||
|
||||
attachmentPermissions.put(name, new PermissionAttachmentInfo(parent, name, null, true));
|
||||
Bukkit.getServer().getPluginManager().subscribeToPermission(name, parent);
|
||||
calculateChildPermissions(perm.getChildren(), false, null);
|
||||
}
|
||||
|
||||
for (PermissionAttachment attachment : attachments) {
|
||||
calculateChildPermissions(attachment.getPermissions(), false, attachment);
|
||||
}
|
||||
|
||||
invalidateCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void clearPermissions() {
|
||||
Set<String> perms = attachmentPermissions.keySet();
|
||||
|
||||
for (String name : perms) {
|
||||
Bukkit.getServer().getPluginManager().unsubscribeFromPermission(name, parent);
|
||||
}
|
||||
|
||||
Bukkit.getServer().getPluginManager().unsubscribeFromDefaultPerms(false, parent);
|
||||
Bukkit.getServer().getPluginManager().unsubscribeFromDefaultPerms(true, parent);
|
||||
|
||||
attachmentPermissions.clear();
|
||||
}
|
||||
|
||||
private void calculateChildPermissions(Map<String, Boolean> children, boolean invert, PermissionAttachment attachment) {
|
||||
for (Map.Entry<String, Boolean> e : children.entrySet()) {
|
||||
Permission perm = Bukkit.getServer().getPluginManager().getPermission(e.getKey());
|
||||
boolean value = e.getValue() ^ invert;
|
||||
String name = e.getKey().toLowerCase();
|
||||
|
||||
attachmentPermissions.put(name, new PermissionAttachmentInfo(parent, name, attachment, value));
|
||||
Bukkit.getServer().getPluginManager().subscribeToPermission(name, parent);
|
||||
|
||||
if (perm != null) {
|
||||
calculateChildPermissions(perm.getChildren(), !value, attachment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<PermissionAttachmentInfo> getEffectivePermissions() {
|
||||
Set<PermissionAttachmentInfo> perms = new HashSet<>();
|
||||
perms.addAll(attachmentPermissions.values());
|
||||
|
||||
perms.addAll(luckPermsPermissions.entrySet().stream()
|
||||
.map(e -> new PermissionAttachmentInfo(parent, e.getKey(), null, e.getValue()))
|
||||
.collect(Collectors.toList()));
|
||||
|
||||
return perms;
|
||||
}
|
||||
|
||||
private class RemoveAttachmentRunnable implements Runnable {
|
||||
private PermissionAttachment attachment;
|
||||
|
||||
private RemoveAttachmentRunnable(PermissionAttachment attachment) {
|
||||
this.attachment = attachment;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
attachment.remove();
|
||||
}
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
private static class AttachmentProcessor implements PermissionProcessor {
|
||||
|
||||
@Getter
|
||||
private final Map<String, PermissionAttachmentInfo> map;
|
||||
|
||||
@Override
|
||||
public Tristate hasPermission(String permission) {
|
||||
if (map.containsKey(permission)) {
|
||||
return Tristate.fromBoolean(map.get(permission).getValue());
|
||||
}
|
||||
|
||||
return Tristate.UNDEFINED;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
private static class BukkitDefaultsProcessor implements PermissionProcessor {
|
||||
private final Supplier<Boolean> isOp;
|
||||
|
||||
@Override
|
||||
public Tristate hasPermission(String permission) {
|
||||
Permission defPerm = Bukkit.getServer().getPluginManager().getPermission(permission);
|
||||
if (defPerm != null) {
|
||||
return Tristate.fromBoolean(defPerm.getDefault().getValue(isOp.get()));
|
||||
} else {
|
||||
return Tristate.UNDEFINED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,39 +22,25 @@
|
||||
|
||||
package me.lucko.luckperms.users;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import me.lucko.luckperms.LPBukkitPlugin;
|
||||
import me.lucko.luckperms.api.event.events.UserPermissionRefreshEvent;
|
||||
import me.lucko.luckperms.api.implementation.internal.UserLink;
|
||||
import org.bukkit.permissions.PermissionAttachment;
|
||||
import me.lucko.luckperms.inject.LPPermissible;
|
||||
import me.lucko.luckperms.utils.Contexts;
|
||||
import org.bukkit.permissions.Permissible;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class BukkitUser extends User {
|
||||
private static Field permissionsField = null;
|
||||
public static Field getPermissionsField() {
|
||||
if (permissionsField == null) {
|
||||
try {
|
||||
permissionsField = PermissionAttachment.class.getDeclaredField("permissions");
|
||||
permissionsField.setAccessible(true);
|
||||
} catch (SecurityException | NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return permissionsField;
|
||||
}
|
||||
|
||||
|
||||
private final LPBukkitPlugin plugin;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private PermissionAttachmentHolder attachment = null;
|
||||
private LPPermissible lpPermissible = null;
|
||||
|
||||
BukkitUser(UUID uuid, LPBukkitPlugin plugin) {
|
||||
super(uuid, plugin);
|
||||
@@ -68,24 +54,28 @@ public class BukkitUser extends User {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void refreshPermissions() {
|
||||
if (attachment == null) {
|
||||
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,
|
||||
plugin.getPossiblePermissions()
|
||||
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()
|
||||
);
|
||||
|
||||
try {
|
||||
// The map in the LP PermissionAttachment is a ConcurrentHashMap. We can modify and iterate over its contents async.
|
||||
Map<String, Boolean> existing = attachment.getPermissions();
|
||||
Map<String, Boolean> existing = lpPermissible.getLuckPermsPermissions();
|
||||
|
||||
boolean different = false;
|
||||
if (toApply.size() != existing.size()) {
|
||||
@@ -103,26 +93,30 @@ public class BukkitUser extends User {
|
||||
if (!different) return;
|
||||
|
||||
existing.clear();
|
||||
lpPermissible.invalidateCache();
|
||||
existing.putAll(toApply);
|
||||
|
||||
/* Must be called sync, as #recalculatePermissions is an unmodified Bukkit API call that is absolutely not thread safe.
|
||||
Shouldn't be too taxing on the server. This only gets called when permissions have actually changed,
|
||||
which is like once per user per login, assuming their permissions don't get modified. */
|
||||
plugin.doSync(() -> {
|
||||
attachment.getAttachment().getPermissible().recalculatePermissions();
|
||||
plugin.getApiProvider().fireEventAsync(new UserPermissionRefreshEvent(new UserLink(this)));
|
||||
});
|
||||
if (plugin.getConfiguration().getAutoOp()) {
|
||||
boolean op = false;
|
||||
|
||||
for (Map.Entry<String, Boolean> e : toApply.entrySet()) {
|
||||
if (e.getKey().equalsIgnoreCase("luckperms.autoop") && e.getValue()) {
|
||||
op = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
final boolean finalOp = op;
|
||||
if (lpPermissible.isOp() != op) {
|
||||
final Permissible parent = lpPermissible.getParent();
|
||||
plugin.doSync(() -> parent.setOp(finalOp));
|
||||
}
|
||||
}
|
||||
|
||||
plugin.getApiProvider().fireEventAsync(new UserPermissionRefreshEvent(new UserLink(this)));
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Getter
|
||||
@EqualsAndHashCode
|
||||
@AllArgsConstructor
|
||||
public static class PermissionAttachmentHolder {
|
||||
private final PermissionAttachment attachment;
|
||||
private final Map<String, Boolean> permissions;
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,7 @@ package me.lucko.luckperms.users;
|
||||
|
||||
import lombok.Getter;
|
||||
import me.lucko.luckperms.LPBukkitPlugin;
|
||||
import me.lucko.luckperms.inject.Injector;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Map;
|
||||
@@ -47,14 +48,16 @@ public class BukkitUserManager extends UserManager {
|
||||
public void preUnload(User user) {
|
||||
if (user instanceof BukkitUser) {
|
||||
BukkitUser u = (BukkitUser) user;
|
||||
|
||||
if (u.getAttachment() != null) {
|
||||
Player player = plugin.getServer().getPlayer(plugin.getUuidCache().getExternalUUID(u.getUuid()));
|
||||
|
||||
if (player != null) {
|
||||
player.removeAttachment(u.getAttachment().getAttachment());
|
||||
Player player = plugin.getServer().getPlayer(plugin.getUuidCache().getExternalUUID(u.getUuid()));
|
||||
if (player != null) {
|
||||
if (u.getLpPermissible() != null) {
|
||||
Injector.unInject(player);
|
||||
u.setLpPermissible(null);
|
||||
}
|
||||
|
||||
if (plugin.getConfiguration().getAutoOp()) {
|
||||
player.setOp(false);
|
||||
}
|
||||
u.setAttachment(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -30,13 +41,12 @@ online-mode: true
|
||||
|
||||
# If the plugin should apply wildcard permissions.
|
||||
# If set to true, LuckPerms will detect wildcard permissions, and resolve & apply all registered permissions matching
|
||||
# the wildcard. This will only work for plugins that define all of their permissions to the server.
|
||||
# the wildcard.
|
||||
apply-wildcards: true
|
||||
|
||||
# If the plugin should parse regex permissions.
|
||||
# If set to true, LuckPerms will detect regex permissions, marked with "r=" at the start of the node, and resolve &
|
||||
# apply all registered permissions matching the regex. This will only work for plugins that define all of their
|
||||
# permissions to the server.
|
||||
# apply all registered permissions matching the regex.
|
||||
apply-regex: true
|
||||
|
||||
# If the plugin should complete and apply shorthand permissions.
|
||||
@@ -46,10 +56,21 @@ apply-shorthand: true
|
||||
# If the plugin should send log notifications to users whenever permissions are modified.
|
||||
log-notify: true
|
||||
|
||||
# If LuckPerms should print to console every time a plugin checks if a player has a permission
|
||||
debug-permission-checks: false
|
||||
|
||||
# If the vanilla OP system is enabled. If set to false, all users will be de-opped, and the op/deop commands will be disabled.
|
||||
enable-ops: true
|
||||
|
||||
# If opped players should be allowed to use LuckPerms commands. Set to false to only allow users with the permission access
|
||||
# If set to true, any user with the permission "luckperms.autoop" will automatically be granted server operator status.
|
||||
# This permission can be inherited, or set on specific servers/worlds, temporarily, etc.
|
||||
# Additionally, setting this to true will force the "enable-ops" option above to false. All users will be de-opped unless
|
||||
# they have the permission node, and the op/deop commands will be disabled.
|
||||
#
|
||||
# It is recommended that you use this option instead of assigning a single '*' permission.
|
||||
auto-op: false
|
||||
|
||||
# If opped players should be allowed to use LuckPerms commands. Set to false to only allow users who have the permissions access to the commands
|
||||
commands-allow-op: true
|
||||
|
||||
# The name of the server used within Vault operations. If you don't want Vault operations to be server specific, set this
|
||||
@@ -84,4 +105,4 @@ data:
|
||||
|
||||
# Set to -1 to disable. If this is the only instance accessing the datastore, you can disable syncing.
|
||||
# e.g. if you're using sqlite or flatfile, this can be set to -1 to save resources.
|
||||
sync-minutes: 3
|
||||
sync-minutes: 3
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luckperms</artifactId>
|
||||
<groupId>me.lucko.luckperms</groupId>
|
||||
<version>2.8-SNAPSHOT</version>
|
||||
<version>2.9-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -22,8 +22,12 @@
|
||||
|
||||
package me.lucko.luckperms;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Splitter;
|
||||
import me.lucko.luckperms.api.data.Callback;
|
||||
import me.lucko.luckperms.commands.CommandManager;
|
||||
import me.lucko.luckperms.commands.Util;
|
||||
import me.lucko.luckperms.constants.Patterns;
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.plugin.Command;
|
||||
import net.md_5.bungee.api.plugin.TabExecutor;
|
||||
@@ -40,7 +44,12 @@ class BungeeCommand extends Command implements TabExecutor {
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender sender, String[] args) {
|
||||
manager.onCommand(BungeeSenderFactory.get().wrap(sender), "bperms", Arrays.asList(args), Callback.empty());
|
||||
manager.onCommand(
|
||||
BungeeSenderFactory.get().wrap(sender),
|
||||
"bperms",
|
||||
Util.stripQuotes(Splitter.on(Patterns.COMMAND_SEPARATOR).omitEmptyStrings().splitToList(Joiner.on(' ').join(args))),
|
||||
Callback.empty()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -33,8 +33,6 @@ import net.md_5.bungee.api.event.*;
|
||||
import net.md_5.bungee.api.plugin.Listener;
|
||||
import net.md_5.bungee.event.EventHandler;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@@ -51,22 +49,18 @@ public class BungeeListener extends AbstractListener implements Listener {
|
||||
@EventHandler
|
||||
public void onPlayerPermissionCheck(PermissionCheckEvent e) {
|
||||
if (!(e.getSender() instanceof ProxiedPlayer)) {
|
||||
e.setHasPermission(true);
|
||||
return;
|
||||
}
|
||||
|
||||
final ProxiedPlayer player = ((ProxiedPlayer) e.getSender());
|
||||
final User user = plugin.getUserManager().get(plugin.getUuidCache().getUUID(player.getUniqueId()));
|
||||
if (user == null) return;
|
||||
|
||||
|
||||
final String server = player.getServer() == null ? null : (player.getServer().getInfo() == null ? null : player.getServer().getInfo().getName());
|
||||
Map<String, Boolean> local = user.getLocalPermissions(plugin.getConfiguration().getServer(), server, null, Collections.singletonList(e.getPermission()));
|
||||
for (Map.Entry<String, Boolean> en : local.entrySet()) {
|
||||
if (en.getKey().equalsIgnoreCase(e.getPermission())) {
|
||||
e.setHasPermission(en.getValue());
|
||||
return;
|
||||
}
|
||||
BungeePlayerCache playerCache = plugin.getPlayerCache().get(plugin.getUuidCache().getUUID(player.getUniqueId()));
|
||||
if (playerCache == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.setHasPermission(playerCache.getPermissionValue(e.getPermission()));
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
@@ -108,17 +102,20 @@ public class BungeeListener extends AbstractListener implements Listener {
|
||||
@EventHandler
|
||||
public void onPlayerPostLogin(PostLoginEvent e) {
|
||||
final ProxiedPlayer player = e.getPlayer();
|
||||
final User user = plugin.getUserManager().get(plugin.getUuidCache().getUUID(e.getPlayer().getUniqueId()));
|
||||
final UUID internal = plugin.getUuidCache().getUUID(e.getPlayer().getUniqueId());
|
||||
final User user = plugin.getUserManager().get(internal);
|
||||
|
||||
if (user == null) {
|
||||
plugin.getProxy().getScheduler().schedule(plugin, () -> player.sendMessage(WARN_MESSAGE), 3, TimeUnit.SECONDS);
|
||||
} else {
|
||||
plugin.getPlayerCache().put(internal, new BungeePlayerCache(plugin, e.getPlayer().getName()));
|
||||
user.refreshPermissions();
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerQuit(PlayerDisconnectEvent e) {
|
||||
plugin.getPlayerCache().remove(plugin.getUuidCache().getUUID(e.getPlayer().getUniqueId()));
|
||||
onLeave(e.getPlayer().getUniqueId());
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
import lombok.Getter;
|
||||
import me.lucko.luckperms.utils.PermissionCalculator;
|
||||
import me.lucko.luckperms.utils.PermissionProcessor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class BungeePlayerCache {
|
||||
|
||||
private final PermissionCalculator calculator;
|
||||
|
||||
@Getter
|
||||
private final Map<String, Boolean> permissions = new ConcurrentHashMap<>();
|
||||
|
||||
public BungeePlayerCache(LuckPermsPlugin plugin, String name) {
|
||||
List<PermissionProcessor> processors = new ArrayList<>(3);
|
||||
processors.add(new PermissionCalculator.MapProcessor(permissions));
|
||||
if (plugin.getConfiguration().getApplyWildcards()) {
|
||||
processors.add(new PermissionCalculator.WildcardProcessor(permissions));
|
||||
}
|
||||
if (plugin.getConfiguration().getApplyRegex()) {
|
||||
processors.add(new PermissionCalculator.RegexProcessor(permissions));
|
||||
}
|
||||
|
||||
calculator = new PermissionCalculator(plugin, name, plugin.getConfiguration().getDebugPermissionChecks(), processors);
|
||||
}
|
||||
|
||||
public void invalidateCache() {
|
||||
calculator.invalidateCache();
|
||||
}
|
||||
|
||||
public boolean getPermissionValue(String permission) {
|
||||
return calculator.getPermissionValue(permission).asBoolean();
|
||||
}
|
||||
}
|
||||
@@ -35,8 +35,8 @@ import java.util.UUID;
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class BungeeSenderFactory extends SenderFactory<CommandSender> {
|
||||
private static BungeeSenderFactory instance = null;
|
||||
public static BungeeSenderFactory get() {
|
||||
if (instance == null){
|
||||
public static synchronized BungeeSenderFactory get() {
|
||||
if (instance == null) {
|
||||
instance = new BungeeSenderFactory();
|
||||
}
|
||||
return instance;
|
||||
|
||||
@@ -30,6 +30,7 @@ import me.lucko.luckperms.commands.CommandManager;
|
||||
import me.lucko.luckperms.commands.ConsecutiveExecutor;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.core.LPConfiguration;
|
||||
import me.lucko.luckperms.core.UuidCache;
|
||||
import me.lucko.luckperms.data.Importer;
|
||||
@@ -46,16 +47,14 @@ import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.plugin.Plugin;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Getter
|
||||
public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
|
||||
private final Map<UUID, BungeePlayerCache> playerCache = new ConcurrentHashMap<>();
|
||||
private final Set<UUID> ignoringLogs = ConcurrentHashMap.newKeySet();
|
||||
private LPConfiguration configuration;
|
||||
private UserManager userManager;
|
||||
@@ -161,8 +160,11 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Sender> getSenders() {
|
||||
return getProxy().getPlayers().stream().map(p -> BungeeSenderFactory.get().wrap(p)).collect(Collectors.toList());
|
||||
public List<Sender> getNotifyListeners() {
|
||||
return getProxy().getPlayers().stream()
|
||||
.map(p -> BungeeSenderFactory.get().wrap(p, Collections.singleton(Permission.LOG_NOTIFY)))
|
||||
.filter(Permission.LOG_NOTIFY::isAuthorized)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -22,21 +22,80 @@
|
||||
|
||||
package me.lucko.luckperms.users;
|
||||
|
||||
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;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class BungeeUser extends User {
|
||||
private final LPBungeePlugin plugin;
|
||||
|
||||
BungeeUser(UUID uuid, LPBungeePlugin plugin) {
|
||||
super(uuid, plugin);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
BungeeUser(UUID uuid, String username, LPBungeePlugin plugin) {
|
||||
super(uuid, username, plugin);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshPermissions() {
|
||||
// Do nothing. Permissions are applied when needed in a listener.
|
||||
public synchronized void refreshPermissions() {
|
||||
ProxiedPlayer player = plugin.getProxy().getPlayer(plugin.getUuidCache().getExternalUUID(getUuid()));
|
||||
if (player == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
BungeePlayerCache playerCache = plugin.getPlayerCache().get(getUuid());
|
||||
if (playerCache == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final String server = player.getServer() == null ? null : (player.getServer().getInfo() == null ? null : player.getServer().getInfo().getName());
|
||||
|
||||
// Calculate the permissions that should be applied. This is done async.
|
||||
Map<String, Boolean> toApply = exportNodes(
|
||||
new Contexts(
|
||||
plugin.getConfiguration().getServer(),
|
||||
server,
|
||||
null,
|
||||
plugin.getConfiguration().getIncludeGlobalPerms(),
|
||||
plugin.getConfiguration().getIncludeGlobalWorldPerms(),
|
||||
true,
|
||||
plugin.getConfiguration().getApplyGlobalGroups(),
|
||||
plugin.getConfiguration().getApplyGlobalWorldGroups()
|
||||
),
|
||||
Collections.emptyList()
|
||||
);
|
||||
|
||||
Map<String, Boolean> existing = playerCache.getPermissions();
|
||||
|
||||
boolean different = false;
|
||||
if (toApply.size() != existing.size()) {
|
||||
different = true;
|
||||
} else {
|
||||
for (Map.Entry<String, Boolean> e : existing.entrySet()) {
|
||||
if (toApply.containsKey(e.getKey()) && toApply.get(e.getKey()) == e.getValue()) {
|
||||
continue;
|
||||
}
|
||||
different = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!different) return;
|
||||
|
||||
existing.clear();
|
||||
playerCache.invalidateCache();
|
||||
existing.putAll(toApply);
|
||||
|
||||
plugin.getApiProvider().fireEventAsync(new UserPermissionRefreshEvent(new UserLink(this)));
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
|
||||
@@ -30,13 +41,12 @@ online-mode: true
|
||||
|
||||
# If the plugin should apply wildcard permissions.
|
||||
# If set to true, LuckPerms will detect wildcard permissions, and resolve & apply all registered permissions matching
|
||||
# the wildcard. This will only work for plugins that define all of their permissions to the server.
|
||||
# the wildcard.
|
||||
apply-wildcards: true
|
||||
|
||||
# If the plugin should parse regex permissions.
|
||||
# If set to true, LuckPerms will detect regex permissions, marked with "r=" at the start of the node, and resolve &
|
||||
# apply all registered permissions matching the regex. This will only work for plugins that define all of their
|
||||
# permissions to the server.
|
||||
# apply all registered permissions matching the regex.
|
||||
apply-regex: true
|
||||
|
||||
# If the plugin should complete and apply shorthand permissions.
|
||||
@@ -46,6 +56,9 @@ apply-shorthand: true
|
||||
# If the plugin should send log notifications to users whenever permissions are modified.
|
||||
log-notify: true
|
||||
|
||||
# If LuckPerms should print to console every time a plugin checks if a player has a permission
|
||||
debug-permission-checks: false
|
||||
|
||||
# Which storage method the plugin should use.
|
||||
# Currently supported: mysql, sqlite, h2, json, yaml, mongodb
|
||||
# Fill out connection info below if you're using MySQL or MongoDB
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luckperms</artifactId>
|
||||
<groupId>me.lucko.luckperms</groupId>
|
||||
<version>2.8-SNAPSHOT</version>
|
||||
<version>2.9-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ public interface LuckPermsPlugin {
|
||||
/**
|
||||
* @return a {@link List} of senders online on the platform
|
||||
*/
|
||||
List<Sender> getSenders();
|
||||
List<Sender> getNotifyListeners();
|
||||
|
||||
/**
|
||||
* @return the console sender of the instance
|
||||
|
||||
@@ -67,7 +67,7 @@ public class ApiProvider implements LuckPermsApi {
|
||||
|
||||
@Override
|
||||
public double getApiVersion() {
|
||||
return 2.8;
|
||||
return 2.9;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+25
@@ -61,6 +61,21 @@ public class LPConfigurationLink implements LPConfiguration {
|
||||
return master.getIncludeGlobalPerms();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getIncludeGlobalWorldPerms() {
|
||||
return master.getIncludeGlobalWorldPerms();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getApplyGlobalGroups() {
|
||||
return master.getApplyGlobalGroups();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getApplyGlobalWorldGroups() {
|
||||
return master.getApplyGlobalWorldGroups();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getOnlineMode() {
|
||||
return master.getOnlineMode();
|
||||
@@ -86,6 +101,11 @@ public class LPConfigurationLink implements LPConfiguration {
|
||||
return master.getLogNotify();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getDebugPermissionChecks() {
|
||||
return master.getDebugPermissionChecks();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getEnableOps() {
|
||||
return master.getEnableOps();
|
||||
@@ -96,6 +116,11 @@ public class LPConfigurationLink implements LPConfiguration {
|
||||
return master.getCommandsAllowOp();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getAutoOp() {
|
||||
return master.getAutoOp();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVaultServer() {
|
||||
return master.getVaultServer();
|
||||
|
||||
+3
-2
@@ -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
|
||||
|
||||
@@ -61,6 +61,7 @@ public class CommandManager {
|
||||
.add(new InfoCommand())
|
||||
.add(new DebugCommand())
|
||||
.add(new ImportCommand())
|
||||
.add(new ExportCommand())
|
||||
.add(new QueueCommand())
|
||||
.add(new MigrationMainCommand())
|
||||
.add(new CreateGroup())
|
||||
|
||||
@@ -47,7 +47,11 @@ public abstract class SenderFactory<T> implements Runnable {
|
||||
protected abstract boolean hasPermission(T t, String node);
|
||||
|
||||
public final Sender wrap(T t) {
|
||||
return new SenderImp(t);
|
||||
return new SenderImp(t, null);
|
||||
}
|
||||
|
||||
public final Sender wrap(T t, Set<Permission> toCheck) {
|
||||
return new SenderImp(t, toCheck);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -81,15 +85,19 @@ public abstract class SenderFactory<T> implements Runnable {
|
||||
|
||||
private final boolean console;
|
||||
|
||||
private SenderImp(T t) {
|
||||
private SenderImp(T t, Set<Permission> toCheck) {
|
||||
this.tRef = new WeakReference<>(t);
|
||||
this.name = factory.getName(t);
|
||||
this.uuid = factory.getUuid(t);
|
||||
this.console = this.uuid.equals(Constants.getConsoleUUID()) || this.uuid.equals(Constants.getImporterUUID());
|
||||
|
||||
if (!this.console) {
|
||||
this.perms = ImmutableMap.copyOf(Arrays.stream(Permission.values())
|
||||
.collect(Collectors.toMap(p -> p, p -> factory.hasPermission(t, p.getNode()))));
|
||||
if (toCheck == null || toCheck.isEmpty()) {
|
||||
this.perms = ImmutableMap.copyOf(Arrays.stream(Permission.values())
|
||||
.collect(Collectors.toMap(p -> p, p -> factory.hasPermission(t, p.getNode()))));
|
||||
} else {
|
||||
this.perms = ImmutableMap.copyOf(toCheck.stream().collect(Collectors.toMap(p -> p, p -> factory.hasPermission(t, p.getNode()))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,22 @@ public class Util {
|
||||
sender.sendMessage(color(Message.PREFIX + message));
|
||||
}
|
||||
|
||||
public static List<String> stripQuotes(List<String> input) {
|
||||
input = new ArrayList<>(input);
|
||||
ListIterator<String> iterator = input.listIterator();
|
||||
while (iterator.hasNext()) {
|
||||
String value = iterator.next();
|
||||
if (!(value.length() >= 3)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (value.charAt(0) == '"' && value.charAt(value.length() - 1) == '"') {
|
||||
iterator.set(value.substring(1, value.length() - 1));
|
||||
}
|
||||
}
|
||||
return input;
|
||||
}
|
||||
|
||||
public static String color(String s) {
|
||||
return translateAlternateColorCodes('&', s);
|
||||
}
|
||||
|
||||
+2
-1
@@ -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;
|
||||
}
|
||||
|
||||
+1
-2
@@ -28,7 +28,6 @@ import me.lucko.luckperms.commands.Predicate;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.commands.SubCommand;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Patterns;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.data.LogEntry;
|
||||
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
||||
@@ -53,7 +52,7 @@ public class GroupSetPermission extends SubCommand<Group> {
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (Patterns.GROUP_MATCH.matcher(node).matches()) {
|
||||
if (node.toLowerCase().startsWith("group.")) {
|
||||
Message.GROUP_USE_INHERIT.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
+1
-2
@@ -28,7 +28,6 @@ import me.lucko.luckperms.commands.Predicate;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.commands.SubCommand;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Patterns;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.data.LogEntry;
|
||||
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
||||
@@ -55,7 +54,7 @@ public class GroupSetTempPermission extends SubCommand<Group> {
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (Patterns.GROUP_MATCH.matcher(node).matches()) {
|
||||
if (node.toLowerCase().startsWith("group.")) {
|
||||
Message.GROUP_USE_INHERIT.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
+1
-2
@@ -28,7 +28,6 @@ import me.lucko.luckperms.commands.Predicate;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.commands.SubCommand;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Patterns;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.data.LogEntry;
|
||||
import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||
@@ -52,7 +51,7 @@ public class GroupUnSetPermission extends SubCommand<Group> {
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (Patterns.GROUP_MATCH.matcher(node).matches()) {
|
||||
if (node.toLowerCase().startsWith("group.")) {
|
||||
Message.GROUP_USE_UNINHERIT.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
+1
-2
@@ -28,7 +28,6 @@ import me.lucko.luckperms.commands.Predicate;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.commands.SubCommand;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Patterns;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.data.LogEntry;
|
||||
import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||
@@ -53,7 +52,7 @@ public class GroupUnsetTempPermission extends SubCommand<Group> {
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (Patterns.GROUP_MATCH.matcher(node).matches()) {
|
||||
if (node.toLowerCase().startsWith("group.")) {
|
||||
Message.GROUP_USE_UNINHERIT.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
+22
@@ -1,3 +1,25 @@
|
||||
/*
|
||||
* 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.commands.migration.subcommands;
|
||||
|
||||
import de.bananaco.bpermissions.api.*;
|
||||
|
||||
+1
@@ -123,6 +123,7 @@ public class MigrationGroupManager extends SubCommand<Object> {
|
||||
}
|
||||
}
|
||||
|
||||
plugin.getDatastore().saveGroup(group);
|
||||
}
|
||||
|
||||
Map<UUID, Map<Map.Entry<String, String>, Boolean>> users = new HashMap<>();
|
||||
|
||||
+4
-4
@@ -118,7 +118,7 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
|
||||
try {
|
||||
for (String node : group.getOwnPermissions(null)) {
|
||||
boolean value = true;
|
||||
if (node.startsWith("!")) {
|
||||
if (node.startsWith("-")) {
|
||||
node = node.substring(1);
|
||||
value = false;
|
||||
}
|
||||
@@ -143,7 +143,7 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
|
||||
for (String world : worlds) {
|
||||
for (String node : group.getOwnPermissions(world)) {
|
||||
boolean value = true;
|
||||
if (node.startsWith("!")) {
|
||||
if (node.startsWith("-")) {
|
||||
node = node.substring(1);
|
||||
value = false;
|
||||
}
|
||||
@@ -262,7 +262,7 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
|
||||
try {
|
||||
for (String node : user.getOwnPermissions(null)) {
|
||||
boolean value = true;
|
||||
if (node.startsWith("!")) {
|
||||
if (node.startsWith("-")) {
|
||||
node = node.substring(1);
|
||||
value = false;
|
||||
}
|
||||
@@ -287,7 +287,7 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
|
||||
for (String world : worlds) {
|
||||
for (String node : user.getOwnPermissions(world)) {
|
||||
boolean value = true;
|
||||
if (node.startsWith("!")) {
|
||||
if (node.startsWith("-")) {
|
||||
node = node.substring(1);
|
||||
value = false;
|
||||
}
|
||||
|
||||
+254
-180
@@ -23,14 +23,17 @@
|
||||
package me.lucko.luckperms.commands.migration.subcommands;
|
||||
|
||||
import com.github.cheesesoftware.PowerfulPermsAPI.*;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
import lombok.Cleanup;
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.api.Logger;
|
||||
import me.lucko.luckperms.api.data.Callback;
|
||||
import me.lucko.luckperms.commands.CommandResult;
|
||||
import me.lucko.luckperms.commands.Predicate;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.commands.SubCommand;
|
||||
import me.lucko.luckperms.commands.migration.subcommands.utils.LPResultRunnable;
|
||||
import me.lucko.luckperms.constants.Constants;
|
||||
import me.lucko.luckperms.core.PermissionHolder;
|
||||
import me.lucko.luckperms.data.LogEntry;
|
||||
@@ -45,39 +48,72 @@ import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import static me.lucko.luckperms.constants.Permission.MIGRATION;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public class MigrationPowerfulPerms extends SubCommand<Object> {
|
||||
/* <sadness>
|
||||
The PowerfulPerms API is a complete joke. Seriously, it would probably be easier reflecting into the actual plugin.
|
||||
Methods move about randomly every version...
|
||||
|
||||
What kind of API requires reflection to function with multiple versions...
|
||||
Doesn't that just defeat the whole god damn point of having an API in the first place?
|
||||
Whatever happened to the concept of depreciation and responsible API creation?
|
||||
I tried to keep reflection to a minimum, but in some places there's no other option.
|
||||
This class is a complete fucking mess for that reason. I sad now :(
|
||||
</sadness> */
|
||||
Whatever happened to depreciation?
|
||||
</sadness> */
|
||||
|
||||
private static Method getPlayerPermissionsMethod = null;
|
||||
private static Method getPlayerGroupsMethod = null;
|
||||
private static Method getGroupMethod = null;
|
||||
|
||||
// lol
|
||||
private static boolean superLegacy = false;
|
||||
private static boolean legacy = false;
|
||||
|
||||
static {
|
||||
try {
|
||||
getPlayerGroupsMethod = PermissionManager.class.getMethod("getPlayerOwnGroups", UUID.class, ResultRunnable.class);
|
||||
getPlayerGroupsMethod.setAccessible(true);
|
||||
} catch (NoSuchMethodException e) {
|
||||
Class.forName("com.github.cheesesoftware.PowerfulPermsAPI.ResponseRunnable");
|
||||
legacy = true;
|
||||
} catch (ClassNotFoundException ignored) {}
|
||||
|
||||
if (legacy) {
|
||||
try {
|
||||
getPlayerGroupsMethod = PermissionManager.class.getMethod("getPlayerGroups", UUID.class, ResultRunnable.class);
|
||||
getPlayerGroupsMethod.setAccessible(true);
|
||||
} catch (NoSuchMethodException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
getPlayerPermissionsMethod = PermissionManager.class.getMethod("getPlayerOwnPermissions", UUID.class, ResultRunnable.class);
|
||||
getPlayerPermissionsMethod.setAccessible(true);
|
||||
} catch (NoSuchMethodException ignored) {}
|
||||
} else {
|
||||
try {
|
||||
getPlayerPermissionsMethod = PermissionManager.class.getMethod("getPlayerOwnPermissions", UUID.class);
|
||||
getPlayerPermissionsMethod.setAccessible(true);
|
||||
} catch (NoSuchMethodException ignored) {}
|
||||
}
|
||||
|
||||
try {
|
||||
getGroupMethod = CachedGroup.class.getMethod("getGroup");
|
||||
getGroupMethod.setAccessible(true);
|
||||
legacy = true;
|
||||
} catch (NoSuchMethodException ignored) {
|
||||
superLegacy = true;
|
||||
} catch (NoSuchMethodException ignored) {}
|
||||
|
||||
if (!legacy) {
|
||||
try {
|
||||
getPlayerGroupsMethod = PermissionManager.class.getMethod("getPlayerOwnGroups", UUID.class);
|
||||
getPlayerGroupsMethod.setAccessible(true);
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
getPlayerGroupsMethod = PermissionManager.class.getMethod("getPlayerOwnGroups", UUID.class, ResultRunnable.class);
|
||||
getPlayerGroupsMethod.setAccessible(true);
|
||||
} catch (NoSuchMethodException e) {
|
||||
try {
|
||||
getPlayerGroupsMethod = PermissionManager.class.getMethod("getPlayerGroups", UUID.class, ResultRunnable.class);
|
||||
getPlayerGroupsMethod.setAccessible(true);
|
||||
} catch (NoSuchMethodException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,6 +133,42 @@ public class MigrationPowerfulPerms extends SubCommand<Object> {
|
||||
}
|
||||
}
|
||||
|
||||
private static void getPlayerPermissions(PermissionManager manager, UUID uuid, Callback<List<Permission>> callback) {
|
||||
if (legacy) {
|
||||
try {
|
||||
getPlayerPermissionsMethod.invoke(manager, uuid, new LPResultRunnable<List<Permission>>() {
|
||||
@Override
|
||||
public void run() {
|
||||
callback.onComplete(getResult());
|
||||
}
|
||||
});
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
ListenableFuture<List<Permission>> lf = (ListenableFuture<List<Permission>>) getPlayerPermissionsMethod.invoke(manager, uuid);
|
||||
try {
|
||||
if (lf.isDone()) {
|
||||
callback.onComplete(lf.get());
|
||||
} else {
|
||||
lf.addListener(() -> {
|
||||
try {
|
||||
callback.onComplete(lf.get());
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}, Runnable::run);
|
||||
}
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private CommandResult run(LuckPermsPlugin plugin, List<String> args) {
|
||||
final Logger log = plugin.getLog();
|
||||
if (!plugin.isPluginLoaded("PowerfulPerms")) {
|
||||
@@ -168,7 +240,7 @@ public class MigrationPowerfulPerms extends SubCommand<Object> {
|
||||
|
||||
// Groups first.
|
||||
log.info("PowerfulPerms Migration: Starting group migration.");
|
||||
Map<Integer, Group> groups = pm.getGroups();
|
||||
Map<Integer, Group> groups = pm.getGroups(); // All versions
|
||||
for (Group g : groups.values()) {
|
||||
plugin.getDatastore().createAndLoadGroup(g.getName().toLowerCase());
|
||||
final me.lucko.luckperms.groups.Group group = plugin.getGroupManager().get(g.getName().toLowerCase());
|
||||
@@ -181,16 +253,16 @@ public class MigrationPowerfulPerms extends SubCommand<Object> {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
for (Permission p : g.getOwnPermissions()) {
|
||||
for (Permission p : g.getOwnPermissions()) { // All versions
|
||||
applyPerm(group, p, plugin);
|
||||
}
|
||||
|
||||
for (Group parent : g.getParents()) {
|
||||
for (Group parent : g.getParents()) { // All versions
|
||||
try {
|
||||
group.setPermission("group." + parent.getName().toLowerCase(), true);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(group).action("setinherit " + parent.getName().toLowerCase())
|
||||
.acted(group).action("setinherit " + parent.getName().toLowerCase()) // All versions
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
@@ -216,156 +288,176 @@ public class MigrationPowerfulPerms extends SubCommand<Object> {
|
||||
User user = plugin.getUserManager().get(uuid);
|
||||
|
||||
// Get a list of Permissions held by the user from the PP API.
|
||||
pm.getPlayerOwnPermissions(uuid, new LPResultRunnable<List<Permission>>() {
|
||||
@Override
|
||||
public void run() {
|
||||
List<Permission> perms = this.getResult();
|
||||
perms.forEach(p -> applyPerm(user, p, plugin));
|
||||
getPlayerPermissions(pm, uuid, perms -> { // Changes each version
|
||||
perms.forEach(p -> applyPerm(user, p, plugin));
|
||||
|
||||
// Update the progress so the user can be saved and unloaded.
|
||||
synchronized (progress) {
|
||||
progress.get(uuid).countDown();
|
||||
if (progress.get(uuid).getCount() == 0) {
|
||||
plugin.getDatastore().saveUser(user);
|
||||
plugin.getUserManager().cleanup(user);
|
||||
}
|
||||
// Update the progress so the user can be saved and unloaded.
|
||||
synchronized (progress) {
|
||||
progress.get(uuid).countDown();
|
||||
if (progress.get(uuid).getCount() == 0) {
|
||||
plugin.getDatastore().saveUser(user);
|
||||
plugin.getUserManager().cleanup(user);
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
// Migrate the user's groups to LuckPerms from PP.
|
||||
try {
|
||||
getPlayerGroupsMethod.invoke(pm, uuid, new LPResultRunnable<LinkedHashMap<String, List<CachedGroup>>>() {
|
||||
@Override
|
||||
public void run() {
|
||||
Map<String, List<CachedGroup>> groups = getResult();
|
||||
|
||||
for (Map.Entry<String, List<CachedGroup>> e : groups.entrySet()) {
|
||||
final String server;
|
||||
if (e.getKey() != null && (e.getKey().equals("") || e.getKey().equalsIgnoreCase("all"))) {
|
||||
server = null;
|
||||
} else {
|
||||
server = e.getKey();
|
||||
}
|
||||
|
||||
// This is horrible. So many random API changes through versions, no depreciation.
|
||||
if (legacy) {
|
||||
e.getValue().stream()
|
||||
.filter(cg -> !cg.isNegated())
|
||||
.map(cg -> {
|
||||
try {
|
||||
return (Group) getGroupMethod.invoke(cg);
|
||||
} catch (IllegalAccessException | InvocationTargetException e1) {
|
||||
e1.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.forEach(g -> {
|
||||
if (g != null) {
|
||||
if (server == null) {
|
||||
try {
|
||||
user.setPermission("group." + g.getName().toLowerCase(), true);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(user).action("addgroup " + g.getName().toLowerCase())
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
user.setPermission("group." + g.getName().toLowerCase(), true, server);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(user).action("addgroup " + g.getName().toLowerCase() + " " + server)
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
e.getValue().stream()
|
||||
.filter(g -> !g.hasExpired() && !g.isNegated())
|
||||
.forEach(g -> {
|
||||
final Group group = pm.getGroup(g.getGroupId());
|
||||
if (g.willExpire()) {
|
||||
if (server == null) {
|
||||
try {
|
||||
user.setPermission("group." + group.getName().toLowerCase(), true, g.getExpirationDate().getTime() / 1000L);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(user).action("addtempgroup " + group.getName().toLowerCase() + " " + g.getExpirationDate().getTime() / 1000L)
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
user.setPermission("group." + group.getName().toLowerCase(), true, server, g.getExpirationDate().getTime() / 1000L);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(user).action("addtempgroup " + group.getName().toLowerCase() + " " + g.getExpirationDate().getTime() / 1000L + " " + server)
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
if (server == null) {
|
||||
try {
|
||||
user.setPermission("group." + group.getName().toLowerCase(), true);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(user).action("addgroup " + group.getName().toLowerCase())
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
user.setPermission("group." + group.getName().toLowerCase(), true, server);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(user).action("addgroup " + group.getName().toLowerCase() + " " + server)
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Update the progress so the user can be saved and unloaded.
|
||||
synchronized (progress) {
|
||||
progress.get(uuid).countDown();
|
||||
if (progress.get(uuid).getCount() == 0) {
|
||||
plugin.getDatastore().saveUser(user);
|
||||
plugin.getUserManager().cleanup(user);
|
||||
}
|
||||
}
|
||||
Callback<Map<String, List<CachedGroup>>> callback = groups1 -> {
|
||||
for (Map.Entry<String, List<CachedGroup>> e : groups1.entrySet()) {
|
||||
final String server;
|
||||
if (e.getKey() != null && (e.getKey().equals("") || e.getKey().equalsIgnoreCase("all"))) {
|
||||
server = null;
|
||||
} else {
|
||||
server = e.getKey();
|
||||
}
|
||||
});
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
log.info("PowerfulPerms Migration: Error");
|
||||
e.printStackTrace();
|
||||
|
||||
if (superLegacy) {
|
||||
e.getValue().stream()
|
||||
.filter(cg -> !cg.isNegated())
|
||||
.map(cg -> {
|
||||
try {
|
||||
return (Group) getGroupMethod.invoke(cg);
|
||||
} catch (IllegalAccessException | InvocationTargetException e1) {
|
||||
e1.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.forEach(g -> {
|
||||
if (g != null) {
|
||||
if (server == null) {
|
||||
try {
|
||||
user.setPermission("group." + g.getName().toLowerCase(), true);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(user).action("addgroup " + g.getName().toLowerCase())
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
user.setPermission("group." + g.getName().toLowerCase(), true, server);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(user).action("addgroup " + g.getName().toLowerCase() + " " + server)
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
e.getValue().stream()
|
||||
.filter(g -> !g.hasExpired() && !g.isNegated())
|
||||
.forEach(g -> {
|
||||
final Group group = pm.getGroup(g.getGroupId());
|
||||
if (g.willExpire()) {
|
||||
if (server == null) {
|
||||
try {
|
||||
user.setPermission("group." + group.getName().toLowerCase(), true, g.getExpirationDate().getTime() / 1000L);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(user).action("addtempgroup " + group.getName().toLowerCase() + " " + g.getExpirationDate().getTime() / 1000L)
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
user.setPermission("group." + group.getName().toLowerCase(), true, server, g.getExpirationDate().getTime() / 1000L);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(user).action("addtempgroup " + group.getName().toLowerCase() + " " + g.getExpirationDate().getTime() / 1000L + " " + server)
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
if (server == null) {
|
||||
try {
|
||||
user.setPermission("group." + group.getName().toLowerCase(), true);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(user).action("addgroup " + group.getName().toLowerCase())
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
user.setPermission("group." + group.getName().toLowerCase(), true, server);
|
||||
LogEntry.build()
|
||||
.actor(Constants.getConsoleUUID()).actorName(Constants.getConsoleName())
|
||||
.acted(user).action("addgroup " + group.getName().toLowerCase() + " " + server)
|
||||
.build().submit(plugin);
|
||||
} catch (Exception ex) {
|
||||
if (!(ex instanceof ObjectAlreadyHasException)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Update the progress so the user can be saved and unloaded.
|
||||
synchronized (progress) {
|
||||
progress.get(uuid).countDown();
|
||||
if (progress.get(uuid).getCount() == 0) {
|
||||
plugin.getDatastore().saveUser(user);
|
||||
plugin.getUserManager().cleanup(user);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (!legacy) {
|
||||
try {
|
||||
ListenableFuture<LinkedHashMap<String, List<CachedGroup>>> future = (ListenableFuture<LinkedHashMap<String, List<CachedGroup>>>) getPlayerGroupsMethod.invoke(pm, uuid);
|
||||
try {
|
||||
if (future.isDone()) {
|
||||
callback.onComplete(future.get());
|
||||
} else {
|
||||
future.addListener(() -> {
|
||||
try {
|
||||
callback.onComplete(future.get());
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}, Runnable::run);
|
||||
}
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
log.info("PowerfulPerms Migration: Error");
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
getPlayerGroupsMethod.invoke(pm, uuid, new LPResultRunnable<LinkedHashMap<String, List<CachedGroup>>>() {
|
||||
@Override
|
||||
public void run() {
|
||||
callback.onComplete(getResult());
|
||||
}
|
||||
});
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
log.info("PowerfulPerms Migration: Error");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -417,7 +509,7 @@ public class MigrationPowerfulPerms extends SubCommand<Object> {
|
||||
}
|
||||
|
||||
long expireAt = 0L;
|
||||
if (!legacy) {
|
||||
if (!superLegacy) {
|
||||
if (p.willExpire()) {
|
||||
expireAt = p.getExpirationDate().getTime() / 1000L;
|
||||
}
|
||||
@@ -508,22 +600,4 @@ public class MigrationPowerfulPerms extends SubCommand<Object> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the default ResultRunnable, callbacks will always run in the same thread. (an async one, hopefully.)
|
||||
* @param <T> type
|
||||
*/
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public abstract class LPResultRunnable<T> extends ResultRunnable<T> {
|
||||
|
||||
public LPResultRunnable() {
|
||||
super();
|
||||
super.sameThread = true;
|
||||
}
|
||||
|
||||
public T getResult() {
|
||||
return super.result;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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.commands.migration.subcommands.utils;
|
||||
|
||||
import com.github.cheesesoftware.PowerfulPermsAPI.ResultRunnable;
|
||||
|
||||
/**
|
||||
* Overrides the default ResultRunnable, callbacks will always run in the same thread. (an async one, hopefully.)
|
||||
* @param <T> type
|
||||
*/
|
||||
public abstract class LPResultRunnable<T> extends ResultRunnable<T> {
|
||||
public LPResultRunnable() {
|
||||
super();
|
||||
super.sameThread = true;
|
||||
}
|
||||
|
||||
public T getResult() {
|
||||
return super.result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -38,6 +38,7 @@ public class DebugCommand extends SingleMainCommand {
|
||||
|
||||
@Override
|
||||
protected CommandResult execute(LuckPermsPlugin plugin, Sender sender, List<String> args, String label) {
|
||||
plugin.getLog().info(sender.getName() + " used the debug command.");
|
||||
Message.DEBUG.send(sender,
|
||||
plugin.getPlayerCount(),
|
||||
plugin.getUserManager().getAll().size(),
|
||||
|
||||
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
* 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.commands.misc;
|
||||
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.api.Logger;
|
||||
import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.commands.CommandResult;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.commands.SingleMainCommand;
|
||||
import me.lucko.luckperms.constants.Constants;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.groups.Group;
|
||||
import me.lucko.luckperms.storage.Datastore;
|
||||
import me.lucko.luckperms.tracks.Track;
|
||||
import me.lucko.luckperms.users.User;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
public class ExportCommand extends SingleMainCommand {
|
||||
public ExportCommand() {
|
||||
super("Export", "/%s export <file>", 1, Permission.MIGRATION);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CommandResult execute(LuckPermsPlugin plugin, Sender sender, List<String> args, String label) {
|
||||
final Logger log = plugin.getLog();
|
||||
|
||||
if (!sender.getUuid().equals(Constants.getConsoleUUID())) {
|
||||
Message.MIGRATION_NOT_CONSOLE.send(sender);
|
||||
return CommandResult.NO_PERMISSION;
|
||||
}
|
||||
|
||||
File f = new File(plugin.getMainDir(), args.get(0));
|
||||
if (f.exists()) {
|
||||
Message.LOG_EXPORT_ALREADY_EXISTS.send(sender, f.getAbsolutePath());
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
try {
|
||||
f.createNewFile();
|
||||
} catch (IOException e) {
|
||||
Message.LOG_EXPORT_FAILURE.send(sender);
|
||||
e.printStackTrace();
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
|
||||
if (!Files.isWritable(f.toPath())) {
|
||||
Message.LOG_EXPORT_NOT_WRITABLE.send(sender, f.getAbsolutePath());
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
|
||||
try (FileWriter fWriter = new FileWriter(f, true); BufferedWriter writer = new BufferedWriter(fWriter)) {
|
||||
log.info("Export: Starting export process.");
|
||||
|
||||
// Export Groups
|
||||
log.info("Export: Exporting all groups.");
|
||||
|
||||
// Create the groups first
|
||||
for (Group group : plugin.getGroupManager().getAll().values()) {
|
||||
write(writer, "/luckperms creategroup " + group.getName());
|
||||
}
|
||||
|
||||
int groupCount = 0;
|
||||
for (Group group : plugin.getGroupManager().getAll().values()) {
|
||||
groupCount++;
|
||||
for (Node node : group.getNodes()) {
|
||||
write(writer, nodeToString(node, group.getName(), true));
|
||||
}
|
||||
}
|
||||
log.info("Export: Exported " + groupCount + " groups.");
|
||||
|
||||
// Export tracks
|
||||
log.info("Export: Exporting all tracks.");
|
||||
|
||||
// Create the tracks first
|
||||
for (Track track : plugin.getTrackManager().getAll().values()) {
|
||||
write(writer, "/luckperms createtrack " + track.getName());
|
||||
}
|
||||
|
||||
int trackCount = 0;
|
||||
for (Track track : plugin.getTrackManager().getAll().values()) {
|
||||
trackCount++;
|
||||
for (String group : track.getGroups()) {
|
||||
write(writer, "/luckperms track " + track.getName() + " append " + group);
|
||||
}
|
||||
}
|
||||
log.info("Export: Exported " + trackCount + " tracks.");
|
||||
|
||||
// Export users
|
||||
log.info("Export: Exporting all users. Finding a list of unique users to export.");
|
||||
Datastore ds = plugin.getDatastore();
|
||||
Set<UUID> users = ds.getUniqueUsers();
|
||||
log.info("Export: Found " + users.size() + " unique users to export.");
|
||||
|
||||
int userCount = 0;
|
||||
for (UUID uuid : users) {
|
||||
userCount++;
|
||||
plugin.getDatastore().loadUser(uuid, "null");
|
||||
User user = plugin.getUserManager().get(uuid);
|
||||
|
||||
for (Node node : user.getNodes()) {
|
||||
if (node.isGroupNode() && node.getGroupName().equalsIgnoreCase("default")) {
|
||||
continue;
|
||||
}
|
||||
write(writer, nodeToString(node, user.getUuid().toString(), false));
|
||||
}
|
||||
|
||||
write(writer, "/luckperms user " + user.getUuid().toString() + " setprimarygroup " + user.getPrimaryGroup());
|
||||
plugin.getUserManager().cleanup(user);
|
||||
}
|
||||
log.info("Export: Exported " + userCount + " users.");
|
||||
|
||||
try {
|
||||
writer.flush();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
Message.LOG_EXPORT_SUCCESS.send(sender, f.getAbsolutePath());
|
||||
return CommandResult.SUCCESS;
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isAuthorized(Sender sender) {
|
||||
return sender.getUuid().equals(Constants.getConsoleUUID());
|
||||
}
|
||||
|
||||
private static void write(BufferedWriter writer, String s) {
|
||||
try {
|
||||
writer.write(s);
|
||||
writer.newLine();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static String nodeToString(Node node, String id, boolean group) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("/luckperms ").append(group ? "group " : "user ").append(id).append(" ");
|
||||
|
||||
if (node.isGroupNode()) {
|
||||
if (node.isTemporary()) {
|
||||
sb.append(group ? "settempinherit " : "addtempgroup ");
|
||||
sb.append(node.getGroupName());
|
||||
sb.append(" ").append(node.getExpiryUnixTime());
|
||||
} else {
|
||||
sb.append(group ? "setinherit " : "addgroup ");
|
||||
sb.append(node.getGroupName());
|
||||
}
|
||||
|
||||
if (node.isWorldSpecific()) {
|
||||
sb.append(" ").append(node.getServer().get()).append(" ").append(node.getWorld().get());
|
||||
} else if (node.isServerSpecific()) {
|
||||
sb.append(" ").append(node.getServer().get());
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
sb.append(node.isTemporary() ? "settemp " : "set ");
|
||||
sb.append(node.getPermission()).append(" ").append(node.getValue());
|
||||
|
||||
if (node.isTemporary()) {
|
||||
sb.append(" ").append(node.getExpiryUnixTime());
|
||||
}
|
||||
|
||||
if (node.isWorldSpecific()) {
|
||||
sb.append(" ").append(node.getServer().get()).append(" ").append(node.getWorld().get());
|
||||
} else if (node.isServerSpecific()) {
|
||||
sb.append(" ").append(node.getServer().get());
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -44,10 +44,14 @@ public class InfoCommand extends SingleMainCommand {
|
||||
final LPConfiguration c = plugin.getConfiguration();
|
||||
Message.INFO.send(sender,
|
||||
plugin.getVersion(),
|
||||
plugin.getType().getFriendlyName(),
|
||||
plugin.getDatastore().getName(),
|
||||
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()),
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
+1
-2
@@ -28,7 +28,6 @@ import me.lucko.luckperms.commands.Predicate;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.commands.SubCommand;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Patterns;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.data.LogEntry;
|
||||
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
||||
@@ -54,7 +53,7 @@ public class UserSetPermission extends SubCommand<User> {
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (Patterns.GROUP_MATCH.matcher(node).matches()) {
|
||||
if (node.toLowerCase().startsWith("group.")) {
|
||||
Message.USER_USE_ADDGROUP.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
+1
-2
@@ -28,7 +28,6 @@ import me.lucko.luckperms.commands.Predicate;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.commands.SubCommand;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Patterns;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.data.LogEntry;
|
||||
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
|
||||
@@ -55,7 +54,7 @@ public class UserSetTempPermission extends SubCommand<User> {
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (Patterns.GROUP_MATCH.matcher(node).matches()) {
|
||||
if (node.toLowerCase().startsWith("group.")) {
|
||||
Message.USER_USE_ADDGROUP.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
+1
-2
@@ -28,7 +28,6 @@ import me.lucko.luckperms.commands.Predicate;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.commands.SubCommand;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Patterns;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.data.LogEntry;
|
||||
import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||
@@ -52,7 +51,7 @@ public class UserUnSetPermission extends SubCommand<User> {
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (Patterns.GROUP_MATCH.matcher(node).matches()) {
|
||||
if (node.toLowerCase().startsWith("group.")) {
|
||||
Message.USER_USE_REMOVEGROUP.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
+1
-2
@@ -28,7 +28,6 @@ import me.lucko.luckperms.commands.Predicate;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.commands.SubCommand;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Patterns;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.data.LogEntry;
|
||||
import me.lucko.luckperms.exceptions.ObjectLacksException;
|
||||
@@ -53,7 +52,7 @@ public class UserUnsetTempPermission extends SubCommand<User> {
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (Patterns.GROUP_MATCH.matcher(node).matches()) {
|
||||
if (node.toLowerCase().startsWith("group.")) {
|
||||
Message.USER_USE_REMOVEGROUP.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
@@ -123,10 +123,14 @@ public enum Message {
|
||||
UPDATE_TASK_RUN("&bRunning update task for all online users.", true),
|
||||
INFO(
|
||||
PREFIX + "&6Running &bLuckPerms v%s&6 by &bLuck&6." + "\n" +
|
||||
PREFIX + "&f-> &ePlatform: &6%s" + "\n" +
|
||||
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" +
|
||||
@@ -332,6 +336,7 @@ public enum Message {
|
||||
IMPORT_END_ERROR_HEADER(
|
||||
PREFIX + "&e(Import) &7------------> &6Showing Error #&e%s &7<------------" + "\n" +
|
||||
PREFIX + "&e(Import) &6Whilst executing: &fCommand #%s" + "\n" +
|
||||
PREFIX + "&e(Import) &6Command: &7%s" + "\n" +
|
||||
PREFIX + "&e(Import) &6Type: &f%s" + "\n" +
|
||||
PREFIX + "&e(Import) &6Output:",
|
||||
false
|
||||
|
||||
@@ -33,32 +33,25 @@ import java.util.regex.PatternSyntaxException;
|
||||
public class Patterns {
|
||||
private static final Map<String, Pattern> CACHE = new ConcurrentHashMap<>();
|
||||
|
||||
public static final Pattern SPACE = Pattern.compile(" ");
|
||||
public static final Pattern SERVER_DELIMITER = Pattern.compile("\\/");
|
||||
public static final Pattern WORLD_DELIMITER = Pattern.compile("\\-");
|
||||
public static final Pattern TEMP_DELIMITER = Pattern.compile("\\$");
|
||||
public static final Pattern DOT = Pattern.compile("\\.");
|
||||
public static final Pattern VERTICAL_BAR = Pattern.compile("\\|");
|
||||
public static final Pattern GROUP_MATCH = Pattern.compile("group\\..*");
|
||||
public static final Pattern NON_ALPHA_NUMERIC = Pattern.compile("[\\/\\$\\.\\-]");
|
||||
public static final Pattern NON_USERNAME = Pattern.compile("[^A-Za-z0-9_]");
|
||||
public static final Pattern COMMAND_SEPARATOR = Pattern.compile(" (?=([^\\\"]*\\\"[^\\\"]*\\\")*[^\\\"]*$)");
|
||||
public static final Pattern NON_ALPHA_NUMERIC = Pattern.compile("[\\/\\$\\.\\- ]");
|
||||
public static final Pattern NON_USERNAME = Pattern.compile("[^A-Za-z0-9_ ]");
|
||||
public static final Pattern SHORTHAND_NODE = Pattern.compile("\\.\\([^.]+\\)");
|
||||
public static final Pattern STRIP_COLOR_PATTERN = Pattern.compile("(?i)" + String.valueOf('§') + "[0-9A-FK-OR]");
|
||||
public static final Pattern NODE_CONTEXTS = Pattern.compile("\\(.+\\).*");
|
||||
|
||||
public static Pattern compile(String regex) throws PatternSyntaxException {
|
||||
if (!CACHE.containsKey(regex)) {
|
||||
Pattern p;
|
||||
try {
|
||||
p = Pattern.compile(regex);
|
||||
} catch (PatternSyntaxException e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
CACHE.put(regex, p);
|
||||
public static Pattern compile(String regex) {
|
||||
try {
|
||||
return CACHE.computeIfAbsent(regex, s -> {
|
||||
try {
|
||||
return Pattern.compile(regex);
|
||||
} catch (PatternSyntaxException e) {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
} catch (NullPointerException e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return CACHE.get(regex);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -111,14 +123,22 @@ public abstract class LPConfiguration<T extends LuckPermsPlugin> {
|
||||
return getBoolean("log-notify", true);
|
||||
}
|
||||
|
||||
public boolean getDebugPermissionChecks() {
|
||||
return getBoolean("debug-permission-checks", false);
|
||||
}
|
||||
|
||||
public boolean getEnableOps() {
|
||||
return getBoolean("enable-ops", true);
|
||||
return !getAutoOp() && getBoolean("enable-ops", true);
|
||||
}
|
||||
|
||||
public boolean getCommandsAllowOp() {
|
||||
return getBoolean("commands-allow-op", true);
|
||||
}
|
||||
|
||||
public boolean getAutoOp() {
|
||||
return getBoolean("auto-op", false);
|
||||
}
|
||||
|
||||
public String getVaultServer() {
|
||||
return getString("vault-server", "global");
|
||||
}
|
||||
|
||||
@@ -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,23 +240,20 @@ 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)) {
|
||||
if (node.getPermission().equals("*") || node.getPermission().equals("'*'")) {
|
||||
if (possibleNodes != null && plugin.getConfiguration().getApplyWildcards()) {
|
||||
possibleNodes.forEach(n -> perms.put(n, true));
|
||||
continue;
|
||||
for (Node node : getAllNodesFiltered(context)) {
|
||||
if (possibleNodes != null && !possibleNodes.isEmpty()) {
|
||||
if (node.getPermission().equals("*") || node.getPermission().equals("'*'")) {
|
||||
if (plugin.getConfiguration().getApplyWildcards()) {
|
||||
possibleNodes.forEach(n -> perms.put(n, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,10 +265,12 @@ public abstract class PermissionHolder {
|
||||
.forEach(s -> perms.put(s, node.getValue()));
|
||||
}
|
||||
|
||||
if (plugin.getConfiguration().getApplyWildcards()) {
|
||||
node.resolveWildcard(possibleNodes).stream()
|
||||
.filter(s -> !perms.containsKey(s))
|
||||
.forEach(s -> perms.put(s, node.getValue()));
|
||||
if (possibleNodes != null && !possibleNodes.isEmpty()) {
|
||||
if (plugin.getConfiguration().getApplyWildcards()) {
|
||||
node.resolveWildcard(possibleNodes).stream()
|
||||
.filter(s -> !perms.containsKey(s))
|
||||
.forEach(s -> perms.put(s, node.getValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -357,7 +367,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) {
|
||||
@@ -390,7 +400,7 @@ public abstract class PermissionHolder {
|
||||
* @throws ObjectAlreadyHasException if the holder has this permission already
|
||||
*/
|
||||
public void setPermission(Node node) throws ObjectAlreadyHasException {
|
||||
if (hasPermission(node, false) == Tristate.TRUE) {
|
||||
if (hasPermission(node, false) != Tristate.UNDEFINED) {
|
||||
throw new ObjectAlreadyHasException();
|
||||
}
|
||||
|
||||
@@ -404,7 +414,7 @@ public abstract class PermissionHolder {
|
||||
* @throws ObjectAlreadyHasException if the holder has this permission already
|
||||
*/
|
||||
public void setTransientPermission(Node node) throws ObjectAlreadyHasException {
|
||||
if (hasPermission(node, true) == Tristate.TRUE) {
|
||||
if (hasPermission(node, true) != Tristate.UNDEFINED) {
|
||||
throw new ObjectAlreadyHasException();
|
||||
}
|
||||
|
||||
@@ -442,7 +452,7 @@ public abstract class PermissionHolder {
|
||||
* @throws ObjectLacksException if the holder doesn't have this node already
|
||||
*/
|
||||
public void unsetPermission(Node node) throws ObjectLacksException {
|
||||
if (hasPermission(node, false) != Tristate.TRUE) {
|
||||
if (hasPermission(node, false) == Tristate.UNDEFINED) {
|
||||
throw new ObjectLacksException();
|
||||
}
|
||||
|
||||
@@ -468,7 +478,7 @@ public abstract class PermissionHolder {
|
||||
* @throws ObjectLacksException if the holder doesn't have this node already
|
||||
*/
|
||||
public void unsetTransientPermission(Node node) throws ObjectLacksException {
|
||||
if (hasPermission(node, true) == Tristate.FALSE) {
|
||||
if (hasPermission(node, true) == Tristate.UNDEFINED) {
|
||||
throw new ObjectLacksException();
|
||||
}
|
||||
|
||||
@@ -540,18 +550,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);
|
||||
}
|
||||
|
||||
@@ -30,14 +30,14 @@ import java.util.Comparator;
|
||||
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class PriorityComparator implements Comparator<Node> {
|
||||
private static final PriorityComparator instance = new PriorityComparator();
|
||||
private static final PriorityComparator INSTANCE = new PriorityComparator();
|
||||
|
||||
public static Comparator<Node> get() {
|
||||
return instance;
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
public static Comparator<Node> reverse() {
|
||||
return instance.reversed();
|
||||
return INSTANCE.reversed();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -74,6 +74,6 @@ public class PriorityComparator implements Comparator<Node> {
|
||||
return o1.getWildcardLevel() > o2.getWildcardLevel() ? 1 : -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return o1.getPermission().compareToIgnoreCase(o2.getPermission()) == 1 ? -1 : 1;
|
||||
}
|
||||
}
|
||||
@@ -22,12 +22,12 @@
|
||||
|
||||
package me.lucko.luckperms.core;
|
||||
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.HashBiMap;
|
||||
import com.google.common.collect.Maps;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* @see me.lucko.luckperms.api.UuidCache for docs
|
||||
@@ -35,7 +35,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
public class UuidCache {
|
||||
|
||||
// External UUID --> Internal UUID
|
||||
private Map<UUID, UUID> cache;
|
||||
private BiMap<UUID, UUID> cache;
|
||||
|
||||
@Getter
|
||||
private final boolean onlineMode;
|
||||
@@ -44,23 +44,16 @@ public class UuidCache {
|
||||
this.onlineMode = onlineMode;
|
||||
|
||||
if (!onlineMode) {
|
||||
cache = new ConcurrentHashMap<>();
|
||||
cache = Maps.synchronizedBiMap(HashBiMap.create());
|
||||
}
|
||||
}
|
||||
|
||||
public UUID getUUID(UUID external) {
|
||||
return onlineMode ? external : (cache.containsKey(external) ? cache.get(external) : external);
|
||||
return onlineMode ? external : cache.getOrDefault(external, external);
|
||||
}
|
||||
|
||||
public UUID getExternalUUID(UUID internal) {
|
||||
if (onlineMode) return internal;
|
||||
|
||||
Optional<UUID> external = cache.entrySet().stream()
|
||||
.filter(e -> e.getValue().equals(internal))
|
||||
.map(Map.Entry::getKey)
|
||||
.findFirst();
|
||||
|
||||
return external.isPresent() ? external.get() : internal;
|
||||
return onlineMode ? internal : cache.inverse().getOrDefault(internal, internal);
|
||||
}
|
||||
|
||||
public void addToCache(UUID external, UUID internal) {
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
package me.lucko.luckperms.data;
|
||||
|
||||
import com.google.common.base.Splitter;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Setter;
|
||||
@@ -31,7 +32,6 @@ import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.commands.Util;
|
||||
import me.lucko.luckperms.constants.Constants;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Patterns;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
|
||||
import java.util.*;
|
||||
@@ -88,7 +88,7 @@ public class Importer {
|
||||
Message.IMPORT_START.send(executor);
|
||||
final Sender fake = new FakeSender(this);
|
||||
|
||||
int index = 0;
|
||||
int index = 1;
|
||||
for (String command : commands) {
|
||||
if (lastMsg < (System.currentTimeMillis() / 1000) - 5) {
|
||||
lastMsg = System.currentTimeMillis() / 1000;
|
||||
@@ -98,11 +98,11 @@ public class Importer {
|
||||
|
||||
executing = index;
|
||||
try {
|
||||
CommandResult result = commandManager.onCommand(fake, "perms", Arrays.asList(Patterns.SPACE.split(command)));
|
||||
getResult(index).setResult(result);
|
||||
CommandResult result = commandManager.onCommand(fake, "perms", Splitter.on(' ').splitToList(command));
|
||||
getResult(index, command).setResult(result);
|
||||
|
||||
} catch (Exception e) {
|
||||
getResult(index).setResult(CommandResult.FAILURE);
|
||||
getResult(index, command).setResult(CommandResult.FAILURE);
|
||||
e.printStackTrace();
|
||||
}
|
||||
index++;
|
||||
@@ -129,7 +129,7 @@ public class Importer {
|
||||
int errIndex = 1;
|
||||
for (Map.Entry<Integer, Result> e : cmdResult.entrySet()) {
|
||||
if (e.getValue().getResult() != null && !e.getValue().getResult().booleanValue()) {
|
||||
Message.IMPORT_END_ERROR_HEADER.send(executor, errIndex, e.getKey(), e.getValue().getResult().toString());
|
||||
Message.IMPORT_END_ERROR_HEADER.send(executor, errIndex, e.getKey(), e.getValue().getCommand(), e.getValue().getResult().toString());
|
||||
for (String s : e.getValue().getOutput()) {
|
||||
Message.IMPORT_END_ERROR_CONTENT.send(executor, s);
|
||||
}
|
||||
@@ -158,22 +158,28 @@ public class Importer {
|
||||
}
|
||||
}
|
||||
|
||||
private Result getResult(int executing) {
|
||||
private Result getResult(int executing, String command) {
|
||||
if (!cmdResult.containsKey(executing)) {
|
||||
cmdResult.put(executing, new Result());
|
||||
cmdResult.put(executing, new Result(command));
|
||||
}
|
||||
|
||||
return cmdResult.get(executing);
|
||||
Result existing = cmdResult.get(executing);
|
||||
|
||||
if (!command.equals("") && existing.getCommand().equals("")) {
|
||||
existing.setCommand(command);
|
||||
}
|
||||
|
||||
return existing;
|
||||
}
|
||||
|
||||
private void logMessage(String msg) {
|
||||
getResult(executing).getOutput().add(Util.stripColor(msg));
|
||||
getResult(executing, "").getOutput().add(Util.stripColor(msg));
|
||||
}
|
||||
|
||||
private static class FakeSender implements Sender {
|
||||
private final Importer instance;
|
||||
|
||||
public FakeSender(Importer instance) {
|
||||
private FakeSender(Importer instance) {
|
||||
this.instance = instance;
|
||||
}
|
||||
|
||||
@@ -199,6 +205,9 @@ public class Importer {
|
||||
}
|
||||
|
||||
private static class Result {
|
||||
@Getter
|
||||
@Setter
|
||||
private String command;
|
||||
|
||||
@Getter
|
||||
private final List<String> output = new ArrayList<>();
|
||||
@@ -206,6 +215,10 @@ public class Importer {
|
||||
@Getter
|
||||
@Setter
|
||||
private CommandResult result = CommandResult.FAILURE;
|
||||
|
||||
private Result(String command) {
|
||||
this.command = command;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -26,14 +26,12 @@ import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.api.event.events.LogNotifyEvent;
|
||||
import me.lucko.luckperms.commands.Sender;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.core.PermissionHolder;
|
||||
import me.lucko.luckperms.groups.Group;
|
||||
import me.lucko.luckperms.tracks.Track;
|
||||
import me.lucko.luckperms.users.User;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class LogEntry extends me.lucko.luckperms.api.LogEntry {
|
||||
public static LogEntryBuilder build() {
|
||||
@@ -58,9 +56,7 @@ public class LogEntry extends me.lucko.luckperms.api.LogEntry {
|
||||
|
||||
final String msg = super.getFormatted();
|
||||
|
||||
List<Sender> senders = plugin.getSenders().stream()
|
||||
.filter(Permission.LOG_NOTIFY::isAuthorized)
|
||||
.collect(Collectors.toList());
|
||||
List<Sender> senders = plugin.getNotifyListeners();
|
||||
senders.add(plugin.getConsoleSender());
|
||||
|
||||
if (sender == null) {
|
||||
|
||||
@@ -1,3 +1,25 @@
|
||||
/*
|
||||
* 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.storage;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
@@ -124,7 +124,7 @@ abstract class FlatfileDatastore extends Datastore {
|
||||
|
||||
@Override
|
||||
public Log getLog() {
|
||||
// TODO Add log viewing support for flatfile D:
|
||||
// Flatfile doesn't support viewing log data from in-game. You can just read the file in a text editor.
|
||||
return Log.builder().build();
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ public class H2Datastore extends SQLDatastore {
|
||||
|
||||
private final File file;
|
||||
private Connection connection = null;
|
||||
private final Object connectionLock = new Object();
|
||||
|
||||
public H2Datastore(LuckPermsPlugin plugin, File file) {
|
||||
super(plugin, "H2");
|
||||
@@ -107,12 +108,14 @@ public class H2Datastore extends SQLDatastore {
|
||||
|
||||
@Override
|
||||
Connection getConnection() throws SQLException {
|
||||
if (connection == null || connection.isClosed()) {
|
||||
try {
|
||||
Class.forName("org.h2.Driver");
|
||||
} catch (ClassNotFoundException ignored) {}
|
||||
synchronized (connectionLock) {
|
||||
if (connection == null || connection.isClosed()) {
|
||||
try {
|
||||
Class.forName("org.h2.Driver");
|
||||
} catch (ClassNotFoundException ignored) {}
|
||||
|
||||
connection = DriverManager.getConnection("jdbc:h2:" + file.getAbsolutePath());
|
||||
connection = DriverManager.getConnection("jdbc:h2:" + file.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
return connection;
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
package me.lucko.luckperms.storage.methods;
|
||||
|
||||
import com.zaxxer.hikari.HikariConfig;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
import lombok.Cleanup;
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
@@ -50,20 +51,32 @@ public class MySQLDatastore extends SQLDatastore {
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
hikari = new HikariDataSource();
|
||||
HikariConfig config = new HikariConfig();
|
||||
|
||||
final String address = configuration.getAddress();
|
||||
final String database = configuration.getDatabase();
|
||||
final String username = configuration.getUsername();
|
||||
final String password = configuration.getPassword();
|
||||
|
||||
hikari.setMaximumPoolSize(10);
|
||||
hikari.setDataSourceClassName("com.mysql.jdbc.jdbc2.optional.MysqlDataSource");
|
||||
hikari.addDataSourceProperty("serverName", address.split(":")[0]);
|
||||
hikari.addDataSourceProperty("port", address.split(":")[1]);
|
||||
hikari.addDataSourceProperty("databaseName", database);
|
||||
hikari.addDataSourceProperty("user", username);
|
||||
hikari.addDataSourceProperty("password", password);
|
||||
config.setMaximumPoolSize(10);
|
||||
config.setPoolName("luckperms");
|
||||
config.setDataSourceClassName("com.mysql.jdbc.jdbc2.optional.MysqlDataSource");
|
||||
config.addDataSourceProperty("serverName", address.split(":")[0]);
|
||||
config.addDataSourceProperty("port", address.split(":")[1]);
|
||||
config.addDataSourceProperty("databaseName", database);
|
||||
config.addDataSourceProperty("user", username);
|
||||
config.addDataSourceProperty("password", password);
|
||||
config.addDataSourceProperty("cachePrepStmts", true);
|
||||
config.addDataSourceProperty("prepStmtCacheSize", 250);
|
||||
config.addDataSourceProperty("prepStmtCacheSqlLimit", 2048);
|
||||
config.addDataSourceProperty("useServerPrepStmts", true);
|
||||
config.addDataSourceProperty("cacheCallableStmts", true);
|
||||
config.addDataSourceProperty("alwaysSendSetIsolation", false);
|
||||
config.addDataSourceProperty("cacheServerConfiguration", true);
|
||||
config.addDataSourceProperty("elideSetAutoCommits", true);
|
||||
config.addDataSourceProperty("useLocalSessionState", true);
|
||||
|
||||
hikari = new HikariDataSource(config);
|
||||
|
||||
if (!setupTables(CREATETABLE_UUID, CREATETABLE_USERS, CREATETABLE_GROUPS, CREATETABLE_TRACKS, CREATETABLE_ACTION)) {
|
||||
plugin.getLog().severe("Error occurred whilst initialising the database.");
|
||||
|
||||
@@ -265,7 +265,7 @@ abstract class SQLDatastore extends Datastore {
|
||||
String uuid = resultSet.getString("uuid");
|
||||
uuids.add(UUID.fromString(uuid));
|
||||
}
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ public class SQLiteDatastore extends SQLDatastore {
|
||||
|
||||
private final File file;
|
||||
private Connection connection = null;
|
||||
private final Object connectionLock = new Object();
|
||||
|
||||
public SQLiteDatastore(LuckPermsPlugin plugin, File file) {
|
||||
super(plugin, "SQLite");
|
||||
@@ -107,12 +108,14 @@ public class SQLiteDatastore extends SQLDatastore {
|
||||
|
||||
@Override
|
||||
Connection getConnection() throws SQLException {
|
||||
if (connection == null || connection.isClosed()) {
|
||||
try {
|
||||
Class.forName("org.sqlite.JDBC");
|
||||
} catch (ClassNotFoundException ignored) {}
|
||||
synchronized (connectionLock) {
|
||||
if (connection == null || connection.isClosed()) {
|
||||
try {
|
||||
Class.forName("org.sqlite.JDBC");
|
||||
} catch (ClassNotFoundException ignored) {}
|
||||
|
||||
connection = DriverManager.getConnection("jdbc:sqlite:" + file.getAbsolutePath());
|
||||
connection = DriverManager.getConnection("jdbc:sqlite:" + file.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
return connection;
|
||||
|
||||
@@ -69,11 +69,11 @@ public class AbstractListener {
|
||||
protected void onLeave(UUID uuid) {
|
||||
final UuidCache cache = plugin.getUuidCache();
|
||||
|
||||
// Unload the user from memory when they disconnect;
|
||||
cache.clearCache(uuid);
|
||||
|
||||
final User user = plugin.getUserManager().get(cache.getUUID(uuid));
|
||||
plugin.getUserManager().unload(user);
|
||||
|
||||
// Unload the user from memory when they disconnect;
|
||||
cache.clearCache(uuid);
|
||||
}
|
||||
|
||||
protected void refreshPlayer(UUID uuid) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
package me.lucko.luckperms.utils;
|
||||
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import lombok.*;
|
||||
import me.lucko.luckperms.api.Tristate;
|
||||
@@ -41,6 +42,7 @@ import java.util.stream.IntStream;
|
||||
public class Node implements me.lucko.luckperms.api.Node {
|
||||
private static final Pattern PREFIX_PATTERN = Pattern.compile("(?i)prefix\\.-?\\d+\\..*");
|
||||
private static final Pattern SUFFIX_PATTERN = Pattern.compile("(?i)suffix\\.-?\\d+\\..*");
|
||||
private static final Pattern META_PATTERN = Pattern.compile("meta\\..*\\..*");
|
||||
|
||||
public static me.lucko.luckperms.api.Node fromSerialisedNode(String s, Boolean b) {
|
||||
return builderFromSerialisedNode(s, b).build();
|
||||
@@ -48,36 +50,36 @@ public class Node implements me.lucko.luckperms.api.Node {
|
||||
|
||||
public static me.lucko.luckperms.api.Node.Builder builderFromSerialisedNode(String s, Boolean b) {
|
||||
if (s.contains("/")) {
|
||||
String[] parts = Patterns.SERVER_DELIMITER.split(s, 2);
|
||||
List<String> parts = Splitter.on('/').limit(2).splitToList(s);
|
||||
// 0=server(+world) 1=node
|
||||
|
||||
// WORLD SPECIFIC
|
||||
if (parts[0].contains("-")) {
|
||||
String[] serverParts = Patterns.WORLD_DELIMITER.split(parts[0], 2);
|
||||
if (parts.get(0).contains("-")) {
|
||||
List<String> serverParts = Splitter.on('-').limit(2).splitToList(parts.get(0));
|
||||
// 0=server 1=world
|
||||
|
||||
if (parts[1].contains("$")) {
|
||||
String[] tempParts = Patterns.TEMP_DELIMITER.split(parts[1], 2);
|
||||
return new Node.Builder(tempParts[0], true).setServerRaw(serverParts[0]).setWorld(serverParts[1])
|
||||
.setExpiry(Long.parseLong(tempParts[1])).setValue(b);
|
||||
if (parts.get(1).contains("$")) {
|
||||
List<String> tempParts = Splitter.on('$').limit(2).splitToList(parts.get(1));
|
||||
return new Node.Builder(tempParts.get(0), true).setServerRaw(serverParts.get(0)).setWorld(serverParts.get(1))
|
||||
.setExpiry(Long.parseLong(tempParts.get(1))).setValue(b);
|
||||
} else {
|
||||
return new Node.Builder(parts[1], true).setServerRaw(serverParts[0]).setWorld(serverParts[1]).setValue(b);
|
||||
return new Node.Builder(parts.get(1), true).setServerRaw(serverParts.get(0)).setWorld(serverParts.get(1)).setValue(b);
|
||||
}
|
||||
|
||||
} else {
|
||||
// SERVER BUT NOT WORLD SPECIFIC
|
||||
if (parts[1].contains("$")) {
|
||||
String[] tempParts = Patterns.TEMP_DELIMITER.split(parts[1], 2);
|
||||
return new Node.Builder(tempParts[0], true).setServerRaw(parts[0]).setExpiry(Long.parseLong(tempParts[1])).setValue(b);
|
||||
if (parts.get(1).contains("$")) {
|
||||
List<String> tempParts = Splitter.on('$').limit(2).splitToList(parts.get(1));
|
||||
return new Node.Builder(tempParts.get(0), true).setServerRaw(parts.get(0)).setExpiry(Long.parseLong(tempParts.get(1))).setValue(b);
|
||||
} else {
|
||||
return new Node.Builder(parts[1], true).setServerRaw(parts[0]).setValue(b);
|
||||
return new Node.Builder(parts.get(1), true).setServerRaw(parts.get(0)).setValue(b);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// NOT SERVER SPECIFIC
|
||||
if (s.contains("$")) {
|
||||
String[] tempParts = Patterns.TEMP_DELIMITER.split(s, 2);
|
||||
return new Node.Builder(tempParts[0], true).setExpiry(Long.parseLong(tempParts[1])).setValue(b);
|
||||
List<String> tempParts = Splitter.on('$').limit(2).splitToList(s);
|
||||
return new Node.Builder(tempParts.get(0), true).setExpiry(Long.parseLong(tempParts.get(1))).setValue(b);
|
||||
} else {
|
||||
return new Node.Builder(s, true).setValue(b);
|
||||
}
|
||||
@@ -100,6 +102,11 @@ public class Node implements me.lucko.luckperms.api.Node {
|
||||
|
||||
private final Map<String, String> extraContexts = new HashMap<>();
|
||||
|
||||
// Cache the state
|
||||
private Tristate isPrefix = Tristate.UNDEFINED;
|
||||
private Tristate isSuffix = Tristate.UNDEFINED;
|
||||
private Tristate isMeta = Tristate.UNDEFINED;
|
||||
|
||||
/**
|
||||
* Make an immutable node instance
|
||||
* @param permission the actual permission node
|
||||
@@ -148,6 +155,9 @@ public class Node implements me.lucko.luckperms.api.Node {
|
||||
}
|
||||
|
||||
public Optional<String> getServer() {
|
||||
if (isWorldSpecific() && server == null) {
|
||||
return Optional.of("global");
|
||||
}
|
||||
return Optional.ofNullable(server);
|
||||
}
|
||||
|
||||
@@ -200,7 +210,7 @@ public class Node implements me.lucko.luckperms.api.Node {
|
||||
|
||||
if (world.startsWith("(") && world.endsWith(")") && world.contains("|")) {
|
||||
final String bits = world.substring(1, world.length() - 1);
|
||||
String[] parts = Patterns.VERTICAL_BAR.split(bits);
|
||||
Iterable<String> parts = Splitter.on('|').split(bits);
|
||||
|
||||
for (String s : parts) {
|
||||
if (s.equalsIgnoreCase(thisWorld)) {
|
||||
@@ -310,7 +320,7 @@ public class Node implements me.lucko.luckperms.api.Node {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
String[] parts = Patterns.DOT.split(getPermission());
|
||||
Iterable<String> parts = Splitter.on('.').split(getPermission());
|
||||
List<Set<String>> nodeParts = new ArrayList<>();
|
||||
|
||||
for (String s : parts) {
|
||||
@@ -321,13 +331,13 @@ public class Node implements me.lucko.luckperms.api.Node {
|
||||
|
||||
final String bits = s.substring(1, s.length() - 1);
|
||||
if (s.contains("|")) {
|
||||
nodeParts.add(new HashSet<>(Arrays.asList(Patterns.VERTICAL_BAR.split(bits))));
|
||||
nodeParts.add(new HashSet<>(Splitter.on('|').splitToList(bits)));
|
||||
} else {
|
||||
String[] range = Patterns.WORLD_DELIMITER.split(bits, 2);
|
||||
if (isChar(range[0], range[1])) {
|
||||
nodeParts.add(getCharRange(range[0].charAt(0), range[1].charAt(0)));
|
||||
} else if (isInt(range[0], range[1])) {
|
||||
nodeParts.add(IntStream.rangeClosed(Integer.parseInt(range[0]), Integer.parseInt(range[1])).boxed()
|
||||
List<String> range = Splitter.on('-').limit(2).splitToList(bits);
|
||||
if (isChar(range.get(0), range.get(1))) {
|
||||
nodeParts.add(getCharRange(range.get(0).charAt(0), range.get(1).charAt(0)));
|
||||
} else if (isInt(range.get(0), range.get(1))) {
|
||||
nodeParts.add(IntStream.rangeClosed(Integer.parseInt(range.get(0)), Integer.parseInt(range.get(1))).boxed()
|
||||
.map(i -> "" + i)
|
||||
.collect(Collectors.toSet())
|
||||
);
|
||||
@@ -420,7 +430,7 @@ public class Node implements me.lucko.luckperms.api.Node {
|
||||
|
||||
@Override
|
||||
public boolean isGroupNode() {
|
||||
return Patterns.GROUP_MATCH.matcher(getPermission()).matches();
|
||||
return getPermission().toLowerCase().startsWith("group.");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -444,7 +454,11 @@ public class Node implements me.lucko.luckperms.api.Node {
|
||||
|
||||
@Override
|
||||
public boolean isMeta() {
|
||||
return getPermission().matches("meta\\..*\\..*");
|
||||
if (isMeta == Tristate.UNDEFINED) {
|
||||
isMeta = Tristate.fromBoolean(META_PATTERN.matcher(getPermission()).matches());
|
||||
}
|
||||
|
||||
return isMeta.asBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -459,7 +473,11 @@ public class Node implements me.lucko.luckperms.api.Node {
|
||||
|
||||
@Override
|
||||
public boolean isPrefix() {
|
||||
return PREFIX_PATTERN.matcher(getPermission()).matches();
|
||||
if (isPrefix == Tristate.UNDEFINED) {
|
||||
isPrefix = Tristate.fromBoolean(PREFIX_PATTERN.matcher(getPermission()).matches());
|
||||
}
|
||||
|
||||
return isPrefix.asBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -468,15 +486,18 @@ public class Node implements me.lucko.luckperms.api.Node {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
String[] prefixPart = Patterns.DOT.split(getPermission().substring("prefix.".length()), 2);
|
||||
Integer i = Integer.parseInt(prefixPart[0]);
|
||||
|
||||
return new AbstractMap.SimpleEntry<>(i, prefixPart[1]);
|
||||
List<String> prefixPart = Splitter.on('.').limit(2).splitToList(getPermission().substring("prefix.".length()));
|
||||
Integer i = Integer.parseInt(prefixPart.get(0));
|
||||
return new AbstractMap.SimpleEntry<>(i, prefixPart.get(1));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSuffix() {
|
||||
return SUFFIX_PATTERN.matcher(getPermission()).matches();
|
||||
if (isSuffix == Tristate.UNDEFINED) {
|
||||
isSuffix = Tristate.fromBoolean(SUFFIX_PATTERN.matcher(getPermission()).matches());
|
||||
}
|
||||
|
||||
return isSuffix.asBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -485,10 +506,9 @@ public class Node implements me.lucko.luckperms.api.Node {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
String[] suffixPart = Patterns.DOT.split(getPermission().substring("suffix.".length()), 2);
|
||||
Integer i = Integer.parseInt(suffixPart[0]);
|
||||
|
||||
return new AbstractMap.SimpleEntry<>(i, suffixPart[1]);
|
||||
List<String> suffixPart = Splitter.on('.').limit(2).splitToList(getPermission().substring("suffix.".length()));
|
||||
Integer i = Integer.parseInt(suffixPart.get(0));
|
||||
return new AbstractMap.SimpleEntry<>(i, suffixPart.get(1));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -632,18 +652,14 @@ public class Node implements me.lucko.luckperms.api.Node {
|
||||
if (!Patterns.NODE_CONTEXTS.matcher(permission).matches()) {
|
||||
this.permission = permission;
|
||||
} else {
|
||||
String[] contextParts = permission.substring(1).split("\\)", 2);
|
||||
List<String> contextParts = Splitter.on(')').limit(2).splitToList(permission.substring(1));
|
||||
// 0 = context, 1 = node
|
||||
this.permission = contextParts[1];
|
||||
|
||||
for (String s : contextParts[0].split("\\,")) {
|
||||
if (!s.contains("=")) {
|
||||
// Not valid
|
||||
continue;
|
||||
}
|
||||
|
||||
String[] context = s.split("\\=", 2);
|
||||
extraContexts.put(context[0], context[1]);
|
||||
this.permission = contextParts.get(1);
|
||||
try {
|
||||
extraContexts.putAll(Splitter.on(',').withKeyValueSeparator('=').split(contextParts.get(0)));
|
||||
} catch (IllegalArgumentException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* 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 lombok.RequiredArgsConstructor;
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.api.Tristate;
|
||||
import me.lucko.luckperms.constants.Patterns;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Calculates and caches permissions
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class PermissionCalculator {
|
||||
private final LuckPermsPlugin plugin;
|
||||
private final String objectName;
|
||||
private final boolean debug;
|
||||
private final List<PermissionProcessor> processors;
|
||||
private final Map<String, Tristate> cache = new ConcurrentHashMap<>();
|
||||
|
||||
public void invalidateCache() {
|
||||
cache.clear();
|
||||
}
|
||||
|
||||
public Tristate getPermissionValue(String permission) {
|
||||
if (debug) {
|
||||
plugin.getLog().info("Checking if " + objectName + " has permission: " + permission);
|
||||
}
|
||||
|
||||
permission = permission.toLowerCase();
|
||||
return cache.computeIfAbsent(permission, this::lookupPermissionValue);
|
||||
}
|
||||
|
||||
private Tristate lookupPermissionValue(String permission) {
|
||||
for (PermissionProcessor processor : processors) {
|
||||
Tristate v = processor.hasPermission(permission);
|
||||
if (v == Tristate.UNDEFINED) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
return Tristate.UNDEFINED;
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
public static class MapProcessor implements PermissionProcessor {
|
||||
|
||||
@Getter
|
||||
private final Map<String, Boolean> map;
|
||||
|
||||
@Override
|
||||
public Tristate hasPermission(String permission) {
|
||||
if (map.containsKey(permission)) {
|
||||
return Tristate.fromBoolean(map.get(permission));
|
||||
}
|
||||
|
||||
return Tristate.UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
public static class RegexProcessor implements PermissionProcessor {
|
||||
|
||||
@Getter
|
||||
private final Map<String, Boolean> map;
|
||||
|
||||
@Override
|
||||
public Tristate hasPermission(String permission) {
|
||||
for (Map.Entry<String, Boolean> e : map.entrySet()) {
|
||||
if (e.getKey().toLowerCase().startsWith("r=")) {
|
||||
Pattern p = Patterns.compile(e.getKey().substring(2));
|
||||
if (p == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (p.matcher(permission).matches()) {
|
||||
return Tristate.fromBoolean(e.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Tristate.UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
public static class WildcardProcessor implements PermissionProcessor {
|
||||
|
||||
@Getter
|
||||
private final Map<String, Boolean> map;
|
||||
|
||||
@Override
|
||||
public Tristate hasPermission(String permission) {
|
||||
String node = permission;
|
||||
|
||||
while (node.contains(".")) {
|
||||
int endIndex = node.lastIndexOf('.');
|
||||
if (endIndex == -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
node = node.substring(0, endIndex);
|
||||
if (!isEmpty(node)) {
|
||||
if (map.containsKey(node + ".*")) {
|
||||
return Tristate.fromBoolean(map.get(node + ".*"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (map.containsKey("'*'")) {
|
||||
return Tristate.fromBoolean(map.get("'*'"));
|
||||
}
|
||||
|
||||
if (map.containsKey("*")) {
|
||||
return Tristate.fromBoolean(map.get("*"));
|
||||
}
|
||||
|
||||
return Tristate.UNDEFINED;
|
||||
}
|
||||
|
||||
private static boolean isEmpty(String s) {
|
||||
if (s.equals("")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
char[] chars = s.toCharArray();
|
||||
for (char c : chars) {
|
||||
if (c != '.') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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 me.lucko.luckperms.api.Tristate;
|
||||
|
||||
public interface PermissionProcessor {
|
||||
|
||||
Tristate hasPermission(String permission);
|
||||
|
||||
}
|
||||
@@ -6,11 +6,13 @@
|
||||
|
||||
<groupId>me.lucko.luckperms</groupId>
|
||||
<artifactId>luckperms</artifactId>
|
||||
<version>2.8-SNAPSHOT</version>
|
||||
<version>2.9-SNAPSHOT</version>
|
||||
<modules>
|
||||
<module>common</module>
|
||||
<module>api</module>
|
||||
<module>standalone</module>
|
||||
<module>bukkit</module>
|
||||
<module>bukkit-legacy</module>
|
||||
<module>bukkit-placeholders</module>
|
||||
<module>bungee</module>
|
||||
<module>sponge</module>
|
||||
@@ -37,7 +39,7 @@
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<release.version>2.8</release.version>
|
||||
<release.version>2.9</release.version>
|
||||
</properties>
|
||||
|
||||
<distributionManagement>
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luckperms</artifactId>
|
||||
<groupId>me.lucko.luckperms</groupId>
|
||||
<version>2.8-SNAPSHOT</version>
|
||||
<version>2.9-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -217,8 +217,11 @@ public class LPSpongePlugin implements LuckPermsPlugin {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Sender> getSenders() {
|
||||
return game.getServer().getOnlinePlayers().stream().map(s -> SpongeSenderFactory.get().wrap(s)).collect(Collectors.toList());
|
||||
public List<Sender> getNotifyListeners() {
|
||||
return game.getServer().getOnlinePlayers().stream()
|
||||
.map(s -> SpongeSenderFactory.get().wrap(s, Collections.singleton(Permission.LOG_NOTIFY)))
|
||||
.filter(Permission.LOG_NOTIFY::isAuthorized)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -22,8 +22,10 @@
|
||||
|
||||
package me.lucko.luckperms;
|
||||
|
||||
import com.google.common.base.Splitter;
|
||||
import me.lucko.luckperms.api.data.Callback;
|
||||
import me.lucko.luckperms.commands.CommandManager;
|
||||
import me.lucko.luckperms.commands.Util;
|
||||
import me.lucko.luckperms.constants.Patterns;
|
||||
import org.spongepowered.api.command.CommandCallable;
|
||||
import org.spongepowered.api.command.CommandException;
|
||||
@@ -34,8 +36,6 @@ import org.spongepowered.api.world.Location;
|
||||
import org.spongepowered.api.world.World;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -47,27 +47,22 @@ class SpongeCommand extends CommandManager implements CommandCallable {
|
||||
|
||||
@Override
|
||||
public CommandResult process(CommandSource source, String s) throws CommandException {
|
||||
onCommand(SpongeSenderFactory.get().wrap(source), "perms", Arrays.asList(Patterns.SPACE.split(s)), Callback.empty());
|
||||
onCommand(
|
||||
SpongeSenderFactory.get().wrap(source),
|
||||
"perms",
|
||||
Util.stripQuotes(Splitter.on(Patterns.COMMAND_SEPARATOR).omitEmptyStrings().splitToList(s)),
|
||||
Callback.empty()
|
||||
);
|
||||
return CommandResult.success();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getSuggestions(CommandSource source, String s, @Nullable Location<World> location) throws CommandException {
|
||||
List<String> args = new ArrayList<>(Arrays.asList(Patterns.SPACE.split(s)));
|
||||
if (s.endsWith(" ")) {
|
||||
args.add("");
|
||||
}
|
||||
|
||||
return onTabComplete(SpongeSenderFactory.get().wrap(source), args);
|
||||
return onTabComplete(SpongeSenderFactory.get().wrap(source), Splitter.on(' ').splitToList(s));
|
||||
}
|
||||
|
||||
public List<String> getSuggestions(CommandSource source, String s) throws CommandException {
|
||||
List<String> args = new ArrayList<>(Arrays.asList(Patterns.SPACE.split(s)));
|
||||
if (s.endsWith(" ")) {
|
||||
args.add("");
|
||||
}
|
||||
|
||||
return onTabComplete(SpongeSenderFactory.get().wrap(source), args);
|
||||
return onTabComplete(SpongeSenderFactory.get().wrap(source), Splitter.on(' ').splitToList(s));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
package me.lucko.luckperms;
|
||||
|
||||
import me.lucko.luckperms.constants.Patterns;
|
||||
import com.google.common.base.Splitter;
|
||||
import me.lucko.luckperms.core.LPConfiguration;
|
||||
import ninja.leaping.configurate.ConfigurationNode;
|
||||
import ninja.leaping.configurate.commented.CommentedConfigurationNode;
|
||||
@@ -70,7 +70,7 @@ class SpongeConfig extends LPConfiguration<LPSpongePlugin> {
|
||||
}
|
||||
|
||||
private ConfigurationNode getNode(String path) {
|
||||
String[] paths = Patterns.DOT.split(path);
|
||||
Iterable<String> paths = Splitter.on('.').split(path);
|
||||
ConfigurationNode node = root;
|
||||
|
||||
for (String s : paths) {
|
||||
|
||||
@@ -35,8 +35,8 @@ import java.util.UUID;
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class SpongeSenderFactory extends SenderFactory<CommandSource> {
|
||||
private static SpongeSenderFactory instance = null;
|
||||
public static SpongeSenderFactory get() {
|
||||
if (instance == null){
|
||||
public static synchronized SpongeSenderFactory get() {
|
||||
if (instance == null) {
|
||||
instance = new SpongeSenderFactory();
|
||||
}
|
||||
return instance;
|
||||
|
||||
@@ -35,9 +35,8 @@ 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 org.spongepowered.api.Sponge;
|
||||
import me.lucko.luckperms.utils.Contexts;
|
||||
import org.spongepowered.api.command.CommandSource;
|
||||
import org.spongepowered.api.entity.living.player.Player;
|
||||
import org.spongepowered.api.service.context.Context;
|
||||
import org.spongepowered.api.service.permission.Subject;
|
||||
import org.spongepowered.api.service.permission.SubjectCollection;
|
||||
@@ -60,9 +59,9 @@ public class LuckPermsSubject implements Subject {
|
||||
private final PermissionHolder holder;
|
||||
private final EnduringData enduringData;
|
||||
private final TransientData transientData;
|
||||
private final LuckPermsService service;
|
||||
protected final LuckPermsService service;
|
||||
|
||||
private LuckPermsSubject(PermissionHolder holder, LuckPermsService service) {
|
||||
LuckPermsSubject(PermissionHolder holder, LuckPermsService service) {
|
||||
this.holder = holder;
|
||||
this.enduringData = new EnduringData(this, service, holder);
|
||||
this.transientData = new TransientData(service, holder);
|
||||
@@ -86,15 +85,6 @@ public class LuckPermsSubject implements Subject {
|
||||
|
||||
@Override
|
||||
public Optional<CommandSource> getCommandSource() {
|
||||
if (holder instanceof User) {
|
||||
final UUID uuid = ((User) holder).getUuid();
|
||||
|
||||
Optional<Player> p = Sponge.getServer().getPlayer(uuid);
|
||||
if (p.isPresent()) {
|
||||
return Optional.of(p.get());
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@@ -171,6 +161,20 @@ public class LuckPermsSubject implements Subject {
|
||||
|
||||
@Override
|
||||
public Optional<String> getOption(Set<Context> set, String s) {
|
||||
if (s.equalsIgnoreCase("prefix")) {
|
||||
String prefix = getChatMeta(true, holder);
|
||||
if (!prefix.equals("")) {
|
||||
return Optional.of(prefix);
|
||||
}
|
||||
}
|
||||
|
||||
if (s.equalsIgnoreCase("suffix")) {
|
||||
String suffix = getChatMeta(false, holder);
|
||||
if (!suffix.equals("")) {
|
||||
return Optional.of(suffix);
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, String> transientOptions = enduringData.getOptions(set);
|
||||
if (transientOptions.containsKey(s)) {
|
||||
return Optional.of(transientOptions.get(s));
|
||||
@@ -194,6 +198,41 @@ public class LuckPermsSubject implements Subject {
|
||||
return SubjectData.GLOBAL_CONTEXT;
|
||||
}
|
||||
|
||||
private String getChatMeta(boolean prefix, PermissionHolder holder) {
|
||||
if (holder == null) return "";
|
||||
|
||||
int priority = Integer.MIN_VALUE;
|
||||
String meta = null;
|
||||
|
||||
for (Node n : holder.getAllNodes(null, Contexts.allowAll())) {
|
||||
if (!n.getValue()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (prefix ? !n.isPrefix() : !n.isSuffix()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!n.shouldApplyOnServer(service.getPlugin().getConfiguration().getVaultServer(), service.getPlugin().getConfiguration().getVaultIncludeGlobal(), false)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* TODO per world
|
||||
if (!n.shouldApplyOnWorld(world, service.getPlugin().getConfiguration().getVaultIncludeGlobal(), false)) {
|
||||
continue;
|
||||
}
|
||||
*/
|
||||
|
||||
Map.Entry<Integer, String> value = prefix ? n.getPrefix() : n.getSuffix();
|
||||
if (value.getKey() > priority) {
|
||||
meta = value.getValue();
|
||||
priority = value.getKey();
|
||||
}
|
||||
}
|
||||
|
||||
return meta == null ? "" : unescapeCharacters(meta);
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
public static class EnduringData implements SubjectData {
|
||||
private final LuckPermsSubject superClass;
|
||||
@@ -305,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;
|
||||
}
|
||||
@@ -432,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;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* 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.api.sponge;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import me.lucko.luckperms.users.User;
|
||||
import me.lucko.luckperms.utils.PermissionCalculator;
|
||||
import me.lucko.luckperms.utils.PermissionProcessor;
|
||||
import org.spongepowered.api.Sponge;
|
||||
import org.spongepowered.api.command.CommandSource;
|
||||
import org.spongepowered.api.entity.living.player.Player;
|
||||
import org.spongepowered.api.service.context.Context;
|
||||
import org.spongepowered.api.util.Tristate;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class LuckPermsUserSubject extends LuckPermsSubject {
|
||||
public static LuckPermsUserSubject wrapUser(User user, LuckPermsService service) {
|
||||
return new LuckPermsUserSubject(user, service);
|
||||
}
|
||||
|
||||
@Getter
|
||||
private final User user;
|
||||
|
||||
private final PermissionCalculator calculator;
|
||||
|
||||
@Getter
|
||||
private final Map<String, Boolean> permissionCache = new ConcurrentHashMap<>();
|
||||
|
||||
private LuckPermsUserSubject(User user, LuckPermsService service) {
|
||||
super(user, service);
|
||||
this.user = user;
|
||||
|
||||
List<PermissionProcessor> processors = new ArrayList<>(5);
|
||||
processors.add(new PermissionCalculator.MapProcessor(permissionCache));
|
||||
if (service.getPlugin().getConfiguration().getApplyWildcards()) {
|
||||
processors.add(new SpongeWildcardProcessor(permissionCache));
|
||||
processors.add(new PermissionCalculator.WildcardProcessor(permissionCache));
|
||||
}
|
||||
if (service.getPlugin().getConfiguration().getApplyRegex()) {
|
||||
processors.add(new PermissionCalculator.RegexProcessor(permissionCache));
|
||||
}
|
||||
processors.add(new SpongeDefaultsProcessor(service));
|
||||
|
||||
calculator = new PermissionCalculator(service.getPlugin(), user.getName(), service.getPlugin().getConfiguration().getDebugPermissionChecks(), processors);
|
||||
}
|
||||
|
||||
public void invalidateCache() {
|
||||
calculator.invalidateCache();
|
||||
}
|
||||
|
||||
// TODO don't ignore context
|
||||
@Override
|
||||
public Tristate getPermissionValue(@NonNull Set<Context> contexts, @NonNull String permission) {
|
||||
me.lucko.luckperms.api.Tristate t = calculator.getPermissionValue(permission);
|
||||
if (t != me.lucko.luckperms.api.Tristate.UNDEFINED) {
|
||||
return Tristate.fromBoolean(t.asBoolean());
|
||||
} else {
|
||||
return Tristate.UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdentifier() {
|
||||
return service.getPlugin().getUuidCache().getExternalUUID(user.getUuid()).toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<CommandSource> getCommandSource() {
|
||||
final UUID uuid = service.getPlugin().getUuidCache().getExternalUUID(user.getUuid());
|
||||
|
||||
Optional<Player> p = Sponge.getServer().getPlayer(uuid);
|
||||
if (p.isPresent()) {
|
||||
return Optional.of(p.get());
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
private static class SpongeWildcardProcessor implements PermissionProcessor {
|
||||
|
||||
@Getter
|
||||
private final Map<String, Boolean> map;
|
||||
|
||||
@Override
|
||||
public me.lucko.luckperms.api.Tristate hasPermission(String permission) {
|
||||
String node = permission;
|
||||
|
||||
while (node.contains(".")) {
|
||||
int endIndex = node.lastIndexOf('.');
|
||||
if (endIndex == -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
node = node.substring(0, endIndex);
|
||||
if (!isEmpty(node)) {
|
||||
if (map.containsKey(node)) {
|
||||
return me.lucko.luckperms.api.Tristate.fromBoolean(map.get(node));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (map.containsKey("'*'")) {
|
||||
return me.lucko.luckperms.api.Tristate.fromBoolean(map.get("'*'"));
|
||||
}
|
||||
|
||||
if (map.containsKey("*")) {
|
||||
return me.lucko.luckperms.api.Tristate.fromBoolean(map.get("*"));
|
||||
}
|
||||
|
||||
return me.lucko.luckperms.api.Tristate.UNDEFINED;
|
||||
}
|
||||
|
||||
private static boolean isEmpty(String s) {
|
||||
if (s.equals("")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
char[] chars = s.toCharArray();
|
||||
for (char c : chars) {
|
||||
if (c != '.') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
private static class SpongeDefaultsProcessor implements PermissionProcessor {
|
||||
private final LuckPermsService service;
|
||||
|
||||
@Override
|
||||
public me.lucko.luckperms.api.Tristate hasPermission(String permission) {
|
||||
Tristate t = service.getDefaults().getPermissionValue(Collections.emptySet(), permission);
|
||||
if (t != Tristate.UNDEFINED) {
|
||||
return me.lucko.luckperms.api.Tristate.fromBoolean(t.asBoolean());
|
||||
} else {
|
||||
return me.lucko.luckperms.api.Tristate.UNDEFINED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+10
-5
@@ -22,11 +22,10 @@
|
||||
|
||||
package me.lucko.luckperms.api.sponge.collections;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
import me.lucko.luckperms.api.sponge.LuckPermsService;
|
||||
import me.lucko.luckperms.api.sponge.LuckPermsSubject;
|
||||
import me.lucko.luckperms.api.sponge.simple.SimpleSubject;
|
||||
import me.lucko.luckperms.api.sponge.simple.SimpleCollection;
|
||||
import me.lucko.luckperms.groups.GroupManager;
|
||||
import org.spongepowered.api.service.context.Context;
|
||||
import org.spongepowered.api.service.permission.PermissionService;
|
||||
@@ -38,10 +37,16 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@AllArgsConstructor
|
||||
public class GroupCollection implements SubjectCollection {
|
||||
private final LuckPermsService service;
|
||||
private final GroupManager manager;
|
||||
private final SimpleCollection fallback;
|
||||
|
||||
public GroupCollection(LuckPermsService service, GroupManager manager) {
|
||||
this.service = service;
|
||||
this.manager = manager;
|
||||
this.fallback = new SimpleCollection(service, "fallback-groups");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdentifier() {
|
||||
@@ -54,7 +59,7 @@ public class GroupCollection implements SubjectCollection {
|
||||
return LuckPermsSubject.wrapHolder(manager.get(id), service);
|
||||
}
|
||||
|
||||
return new SimpleSubject(id, service, this);
|
||||
return fallback.get(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -84,6 +89,6 @@ public class GroupCollection implements SubjectCollection {
|
||||
|
||||
@Override
|
||||
public Subject getDefaults() {
|
||||
return new SimpleSubject("default", service, this);
|
||||
return service.getDefaults();
|
||||
}
|
||||
}
|
||||
+45
-24
@@ -22,12 +22,11 @@
|
||||
|
||||
package me.lucko.luckperms.api.sponge.collections;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import me.lucko.luckperms.api.sponge.LuckPermsService;
|
||||
import me.lucko.luckperms.api.sponge.LuckPermsSubject;
|
||||
import me.lucko.luckperms.api.sponge.simple.SimpleSubject;
|
||||
import me.lucko.luckperms.core.PermissionHolder;
|
||||
import me.lucko.luckperms.api.sponge.LuckPermsUserSubject;
|
||||
import me.lucko.luckperms.api.sponge.simple.SimpleCollection;
|
||||
import me.lucko.luckperms.users.User;
|
||||
import me.lucko.luckperms.users.UserManager;
|
||||
import org.spongepowered.api.service.context.Context;
|
||||
@@ -39,50 +38,75 @@ import org.spongepowered.api.service.permission.SubjectData;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@AllArgsConstructor
|
||||
public class UserCollection implements SubjectCollection {
|
||||
private final LuckPermsService service;
|
||||
private final UserManager manager;
|
||||
private final SimpleCollection fallback;
|
||||
|
||||
@Getter
|
||||
private final Map<UUID, LuckPermsUserSubject> users = new ConcurrentHashMap<>();
|
||||
|
||||
public UserCollection(LuckPermsService service, UserManager manager) {
|
||||
this.service = service;
|
||||
this.manager = manager;
|
||||
this.fallback = new SimpleCollection(service, "fallback-users");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdentifier() {
|
||||
return PermissionService.SUBJECTS_USER;
|
||||
}
|
||||
|
||||
private void load(UUID uuid) {
|
||||
UUID internal = service.getPlugin().getUuidCache().getUUID(uuid);
|
||||
if (!manager.isLoaded(internal)) {
|
||||
return;
|
||||
}
|
||||
|
||||
User user = manager.get(internal);
|
||||
users.put(internal, LuckPermsUserSubject.wrapUser(user, service));
|
||||
}
|
||||
|
||||
public void unload(UUID uuid) {
|
||||
users.remove(service.getPlugin().getUuidCache().getUUID(uuid));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Subject get(@NonNull String id) {
|
||||
PermissionHolder holder = null;
|
||||
public synchronized Subject get(@NonNull String id) {
|
||||
try {
|
||||
UUID u = UUID.fromString(id);
|
||||
UUID u = service.getPlugin().getUuidCache().getUUID(UUID.fromString(id));
|
||||
if (users.containsKey(u)) {
|
||||
return users.get(u);
|
||||
}
|
||||
|
||||
if (manager.isLoaded(u)) {
|
||||
holder = manager.get(u);
|
||||
load(u);
|
||||
return users.get(u);
|
||||
}
|
||||
|
||||
} catch (IllegalArgumentException e) {
|
||||
User user = manager.get(id);
|
||||
if (user != null) {
|
||||
holder = user;
|
||||
for (LuckPermsUserSubject subject : users.values()) {
|
||||
if (subject.getUser().getName().equals(id)) {
|
||||
return subject;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (holder != null) {
|
||||
return LuckPermsSubject.wrapHolder(holder, service);
|
||||
}
|
||||
|
||||
service.getPlugin().getLog().warn("Couldn't get subject for: " + id);
|
||||
|
||||
// What am I meant to do here? What if no user is loaded? Load it? Create it?
|
||||
// If I do load/create it, this method should always be called async??.... errr.
|
||||
return new SimpleSubject(id, service, this);
|
||||
return fallback.get(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasRegistered(@NonNull String id) {
|
||||
try {
|
||||
UUID u = UUID.fromString(id);
|
||||
return manager.isLoaded(u);
|
||||
return manager.isLoaded(service.getPlugin().getUuidCache().getUUID(u));
|
||||
} catch (IllegalArgumentException e) {
|
||||
User user = manager.get(id);
|
||||
return user != null;
|
||||
@@ -91,9 +115,7 @@ public class UserCollection implements SubjectCollection {
|
||||
|
||||
@Override
|
||||
public Iterable<Subject> getAllSubjects() {
|
||||
return manager.getAll().values().stream()
|
||||
.map(u -> LuckPermsSubject.wrapHolder(u, service))
|
||||
.collect(Collectors.toList());
|
||||
return users.values().stream().collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -103,14 +125,13 @@ public class UserCollection implements SubjectCollection {
|
||||
|
||||
@Override
|
||||
public Map<Subject, Boolean> getAllWithPermission(@NonNull Set<Context> contexts, @NonNull String node) {
|
||||
return manager.getAll().values().stream()
|
||||
.map(u -> LuckPermsSubject.wrapHolder(u, service))
|
||||
return users.values().stream()
|
||||
.filter(sub -> sub.hasPermission(contexts, node))
|
||||
.collect(Collectors.toMap(sub -> sub, sub -> sub.getPermissionValue(contexts, node).asBoolean()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Subject getDefaults() {
|
||||
return new SimpleSubject("default", service, this);
|
||||
return service.getDefaults();
|
||||
}
|
||||
}
|
||||
@@ -47,7 +47,7 @@ public class SimpleCollection implements SubjectCollection {
|
||||
private final Map<String, Subject> subjects = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public Subject get(@NonNull String id) {
|
||||
public synchronized Subject get(@NonNull String id) {
|
||||
if (!subjects.containsKey(id)) {
|
||||
subjects.put(id, new SimpleSubject(id, service, this));
|
||||
}
|
||||
|
||||
@@ -23,7 +23,14 @@
|
||||
package me.lucko.luckperms.users;
|
||||
|
||||
import me.lucko.luckperms.LPSpongePlugin;
|
||||
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;
|
||||
import java.util.UUID;
|
||||
|
||||
class SpongeUser extends User {
|
||||
@@ -40,25 +47,53 @@ class SpongeUser extends User {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshPermissions() {
|
||||
// Do nothing. Should be grabbed from PermissionService.
|
||||
/*
|
||||
plugin.doSync(() -> {
|
||||
Optional<Player> p = plugin.getGame().getServer().getPlayer(plugin.getUuidCache().getExternalUUID(getUuid()));
|
||||
if (!p.isPresent()) return;
|
||||
public synchronized void refreshPermissions() {
|
||||
UserCollection uc = plugin.getService().getUserSubjects();
|
||||
if (!uc.getUsers().containsKey(getUuid())) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Player player = p.get();
|
||||
// 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(
|
||||
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()
|
||||
);
|
||||
|
||||
// Clear existing permissions
|
||||
player.getSubjectData().clearParents();
|
||||
player.getSubjectData().clearPermissions();
|
||||
try {
|
||||
LuckPermsUserSubject us = uc.getUsers().get(getUuid());
|
||||
Map<String, Boolean> existing = us.getPermissionCache();
|
||||
|
||||
boolean different = false;
|
||||
if (toApply.size() != existing.size()) {
|
||||
different = true;
|
||||
} else {
|
||||
for (Map.Entry<String, Boolean> e : existing.entrySet()) {
|
||||
if (toApply.containsKey(e.getKey()) && toApply.get(e.getKey()) == e.getValue()) {
|
||||
continue;
|
||||
}
|
||||
different = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!different) return;
|
||||
|
||||
existing.clear();
|
||||
us.invalidateCache();
|
||||
existing.putAll(toApply);
|
||||
|
||||
// Re-add all defined permissions for the user
|
||||
final String world = player.getWorld().getName();
|
||||
Map<String, Boolean> local = getLocalPermissions(getPlugin().getConfiguration().getServer(), world, null);
|
||||
local.entrySet().forEach(e -> player.getSubjectData().setPermission(Collections.emptySet(), e.getKey(), Tristate.fromBoolean(e.getValue())));
|
||||
plugin.getApiProvider().fireEventAsync(new UserPermissionRefreshEvent(new UserLink(this)));
|
||||
});
|
||||
*/
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,6 +38,7 @@ public class SpongeUserManager extends UserManager {
|
||||
public void cleanup(User user) {
|
||||
if (!plugin.getGame().getServer().getPlayer(plugin.getUuidCache().getExternalUUID(user.getUuid())).isPresent()) {
|
||||
unload(user);
|
||||
plugin.getService().getUserSubjects().unload(user.getUuid());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -26,19 +37,21 @@ online-mode=true
|
||||
|
||||
# If the plugin should apply wildcard permissions.
|
||||
# If set to true, LuckPerms will detect wildcard permissions, and resolve & apply all registered permissions matching
|
||||
# the wildcard. This will only work for plugins that define all of their permissions to the server.
|
||||
# the wildcard.
|
||||
apply-wildcards=true
|
||||
|
||||
# If the plugin should parse regex permissions.
|
||||
# If set to true, LuckPerms will detect regex permissions, marked with "r=" at the start of the node, and resolve &
|
||||
# apply all registered permissions matching the regex. This will only work for plugins that define all of their
|
||||
# permissions to the server.
|
||||
# apply all registered permissions matching the regex.
|
||||
apply-regex=true
|
||||
|
||||
# If the plugin should complete and apply shorthand permissions.
|
||||
# If set to true, LuckPerms will detect and expand shorthand node patterns.
|
||||
apply-shorthand=true
|
||||
|
||||
# If LuckPerms should print to console every time a plugin checks if a player has a permission
|
||||
debug-permission-checks=false
|
||||
|
||||
# If the plugin should send log notifications to users whenever permissions are modified.
|
||||
log-notify=true
|
||||
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>luckperms</artifactId>
|
||||
<groupId>me.lucko.luckperms</groupId>
|
||||
<version>2.9-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>luckperms-standalone</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<build>
|
||||
<defaultGoal>clean package</defaultGoal>
|
||||
<finalName>LuckPermsStandalone-${release.version}.${git.closest.tag.commit.count}</finalName>
|
||||
<sourceDirectory>${basedir}/src/main/java</sourceDirectory>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.5.1</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>3.0.2</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<mainClass>me.lucko.luckperms.LPStandaloneApp</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>2.4.3</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<minimizeJar>false</minimizeJar>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>org.slf4j</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.slf4j</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.zaxxer.hikari</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.hikari</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.mongodb</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.mongodb</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.bson</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.bson</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.h2</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.h2</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.sqlite</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.sqlite</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>pl.project13.maven</groupId>
|
||||
<artifactId>git-commit-id-plugin</artifactId>
|
||||
<version>2.2.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>revision</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<injectAllReactorProjects>true</injectAllReactorProjects>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<!-- LuckPerms Common -->
|
||||
<dependency>
|
||||
<groupId>me.lucko.luckperms</groupId>
|
||||
<artifactId>luckperms-common</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<!-- LuckPerms API -->
|
||||
<dependency>
|
||||
<groupId>me.lucko.luckperms</groupId>
|
||||
<artifactId>luckperms-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<!-- Lombok -->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.16.10</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- gson -->
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.7</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<!-- guava -->
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>19.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import me.lucko.luckperms.internal.StandaloneBase;
|
||||
|
||||
public class LPStandaloneApp {
|
||||
private StandaloneBase standaloneBase;
|
||||
|
||||
public static void main(String[] args) {
|
||||
new LPStandaloneApp().start();
|
||||
}
|
||||
|
||||
public void start() {
|
||||
standaloneBase = new StandaloneBase(this);
|
||||
LuckPerms.registerProvider(standaloneBase.getApiProvider());
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
standaloneBase.shutdown();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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.gui;
|
||||
|
||||
public class InterfaceManager {
|
||||
// TODO
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* 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.internal;
|
||||
|
||||
import lombok.Getter;
|
||||
import me.lucko.luckperms.LPStandaloneApp;
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.api.Logger;
|
||||
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.constants.Constants;
|
||||
import me.lucko.luckperms.constants.Message;
|
||||
import me.lucko.luckperms.constants.Permission;
|
||||
import me.lucko.luckperms.core.LPConfiguration;
|
||||
import me.lucko.luckperms.core.UuidCache;
|
||||
import me.lucko.luckperms.data.Importer;
|
||||
import me.lucko.luckperms.groups.GroupManager;
|
||||
import me.lucko.luckperms.storage.Datastore;
|
||||
import me.lucko.luckperms.tracks.TrackManager;
|
||||
import me.lucko.luckperms.users.StandaloneUserManager;
|
||||
import me.lucko.luckperms.users.UserManager;
|
||||
import me.lucko.luckperms.utils.LogFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
@Getter
|
||||
public class StandaloneBase implements LuckPermsPlugin {
|
||||
private final ExecutorService threadPool = Executors.newCachedThreadPool();
|
||||
|
||||
private final java.util.logging.Logger logger;
|
||||
|
||||
private final UserManager userManager;
|
||||
private final GroupManager groupManager;
|
||||
private final TrackManager trackManager;
|
||||
private final LPConfiguration configuration;
|
||||
private final Datastore datastore;
|
||||
private final Logger log;
|
||||
private final UuidCache uuidCache;
|
||||
private final ApiProvider apiProvider;
|
||||
|
||||
public StandaloneBase(LPStandaloneApp app) {
|
||||
logger = java.util.logging.Logger.getGlobal();
|
||||
log = LogFactory.wrap(logger);
|
||||
|
||||
configuration = new StandaloneConfiguration(this);
|
||||
|
||||
// TODO datastore
|
||||
datastore = null;
|
||||
// Load everything, including all users.
|
||||
|
||||
uuidCache = new UuidCache(true);
|
||||
userManager = new StandaloneUserManager(this);
|
||||
groupManager = new GroupManager(this);
|
||||
trackManager = new TrackManager();
|
||||
|
||||
apiProvider = new ApiProvider(this);
|
||||
|
||||
// TODO callback to the app, start gui stuff?
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
datastore.shutdown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return "2.9.0"; // TODO set dynamically
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlatformType getType() {
|
||||
return PlatformType.STANDALONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getMainDir() {
|
||||
return null; // Is this needed? TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getDataFolder() {
|
||||
return null; // Is this needed? TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runUpdateTask() {
|
||||
// Is this needed?? TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAsync(Runnable r) {
|
||||
threadPool.execute(r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doSync(Runnable r) {
|
||||
threadPool.execute(r);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Methods below are only required in plugins.
|
||||
* They're just left empty / default.
|
||||
*/
|
||||
|
||||
|
||||
@Override
|
||||
public Importer getImporter() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConsecutiveExecutor getConsecutiveExecutor() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message getPlayerStatus(UUID uuid) {
|
||||
return Message.PLAYER_OFFLINE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPlayerCount() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getPlayerList() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Sender> getNotifyListeners() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sender getConsoleSender() {
|
||||
return new Sender() {
|
||||
@Override
|
||||
public String getName() {
|
||||
return Constants.getConsoleName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUuid() {
|
||||
return Constants.getConsoleUUID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(String s) {
|
||||
getLogger().info(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(Permission permission) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getPossiblePermissions() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<UUID> getIgnoringLogs() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getPlugin(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getService(Class clazz) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID(String playerName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPluginLoaded(String name) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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.internal;
|
||||
|
||||
import me.lucko.luckperms.core.LPConfiguration;
|
||||
|
||||
public class StandaloneConfiguration extends LPConfiguration<StandaloneBase> {
|
||||
public StandaloneConfiguration(StandaloneBase plugin) {
|
||||
super(plugin, "global", true, "null");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void set(String path, Object value) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getString(String path, String def) {
|
||||
return def;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getInt(String path, int def) {
|
||||
return def;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean getBoolean(String path, boolean def) {
|
||||
return def;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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.users;
|
||||
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class StandaloneUser extends User {
|
||||
|
||||
StandaloneUser(UUID uuid, LuckPermsPlugin plugin) {
|
||||
super(uuid, plugin);
|
||||
}
|
||||
|
||||
StandaloneUser(UUID uuid, String username, LuckPermsPlugin plugin) {
|
||||
super(uuid, username, plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshPermissions() {
|
||||
// Do nothing.
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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.users;
|
||||
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class StandaloneUserManager extends UserManager {
|
||||
private final LuckPermsPlugin plugin;
|
||||
|
||||
public StandaloneUserManager(LuckPermsPlugin plugin) {
|
||||
super(plugin);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanup(User user) {
|
||||
// unload(user);
|
||||
// never unload????? TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public User make(UUID id) {
|
||||
return new StandaloneUser(id, plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public User make(UUID uuid, String username) {
|
||||
return new StandaloneUser(uuid, username, plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAllUsers() {
|
||||
getAll().values().forEach(u -> plugin.getDatastore().loadUser(u.getUuid(), u.getName()));
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user