Initial commit

This commit is contained in:
Luck 2016-05-22 01:57:10 +01:00
commit dc1e06ebce
70 changed files with 4044 additions and 0 deletions

37
.gitignore vendored Normal file
View File

@ -0,0 +1,37 @@
# built application files
*.jar
# Java class files
*.class
# Local configuration file (sdk path, etc)
logs/
# Eclipse project files
.classpath
.project
# Intellij project files
*.iml
*.ipr
*.iws
.idea/
# Gradle
.gradletasknamecache
.gradle/
build/
bin/
gradle/
gradlew*
# Maven
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties

21
LICENSE.md Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2016 Luck
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.

28
README.md Normal file
View File

@ -0,0 +1,28 @@
# LuckPerms
A quite possibly shit™ permissions implementation for Bukkit/BungeeCord.
### Why?
Yeah, I don't know. There are other more advanced, optimized, better programmed and thoroughly tested alternative plugins around, you should probably use those instead. I just wanted some specific features, and something that was compatible with BungeeCord.
### Features
- **Group inheritance** - users can be members of multiple groups, groups can inherit other groups
- **Multi-server support** - data is synced across all servers/platforms
- **Per-server permissions/groups** - define permissions that only apply on certain servers
- **Vault Support** - hooks into Vault to integrate with other plugins
- **Everything is configured using commands** - no editing yml files, yuck
- **Efficient** - maybe? Who knows, it might be.
- **BungeeCord compatible** - my main motive for making this was that all other Bungee/Bukkit compatible perms plugins are utter aids. (At least, I couldn't find any decent ones)
### Caveats
- Only supports MySQL
- Not at all tested and could be super unreliable
- It's quite possibly shit™
So, not anything major, really ¯\ _(ツ)_ /¯
### Commands
Command usage is printed when you supply too little arguments.
Bukkit: `/luckperms` `/perms` `/permissions` `/lp` `/perm`
Bungee: `/luckpermsbungee` `/bperms` `/bpermissions` `/lpb` `/bperm`

79
bukkit/pom.xml Normal file
View File

@ -0,0 +1,79 @@
<?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</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>luckperms-bukkit</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>LuckPerms</name>
<build>
<defaultGoal>clean package</defaultGoal>
<finalName>LuckPerms</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.2</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.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<minimizeJar>true</minimizeJar>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<!-- BukkitAPI -->
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
<version>1.8.8-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<!-- Vault -->
<dependency>
<groupId>net.milkbowl.vault</groupId>
<artifactId>VaultAPI</artifactId>
<version>1.5</version>
<scope>provided</scope>
</dependency>
<!-- LuckPerms Common -->
<dependency>
<groupId>me.lucko</groupId>
<artifactId>luckperms-common</artifactId>
<version>${project.parent.version}</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,71 @@
package me.lucko.luckperms;
import me.lucko.luckperms.utils.LPConfiguration;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
import java.io.File;
import java.io.IOException;
public class BukkitConfig implements LPConfiguration {
private final LPBukkitPlugin plugin;
private YamlConfiguration configuration;
public BukkitConfig(LPBukkitPlugin plugin) {
this.plugin = plugin;
create();
}
private void create() {
File configFile = new File(plugin.getDataFolder(), "config.yml");
if (!configFile.exists()) {
configFile.getParentFile().mkdirs();
plugin.saveResource("config.yml", false);
}
configuration = new YamlConfiguration();
try {
configuration.load(configFile);
} catch (InvalidConfigurationException | IOException e) {
e.printStackTrace();
}
}
@Override
public String getServer() {
return configuration.getString("server");
}
@Override
public String getPrefix() {
return configuration.getString("prefix");
}
@Override
public int getSyncTime() {
return configuration.getInt("sql.sync-minutes");
}
@Override
public String getDefaultGroupNode() {
return "luckperms.group." + configuration.getString("default-group");
}
@Override
public String getDefaultGroupName() {
return configuration.getString("default-group");
}
@Override
public boolean getIncludeGlobalPerms() {
return configuration.getBoolean("include-global");
}
@Override
public String getDatabaseValue(String value) {
return configuration.getString("sql." + value);
}
}

View File

@ -0,0 +1,30 @@
package me.lucko.luckperms;
import me.lucko.luckperms.commands.CommandManager;
import me.lucko.luckperms.commands.Sender;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import java.util.Arrays;
class CommandManagerBukkit extends CommandManager implements CommandExecutor {
CommandManagerBukkit(LuckPermsPlugin plugin) {
super(plugin);
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
return onCommand(new Sender() {
@Override
public void sendMessage(String s) {
sender.sendMessage(s);
}
@Override
public boolean hasPermission(String node) {
return sender.hasPermission(node);
}
}, Arrays.asList(args));
}
}

View File

@ -0,0 +1,109 @@
package me.lucko.luckperms;
import lombok.Getter;
import me.lucko.luckperms.data.Datastore;
import me.lucko.luckperms.data.DatastoreConfiguration;
import me.lucko.luckperms.data.HikariDatastore;
import me.lucko.luckperms.groups.GroupManager;
import me.lucko.luckperms.listeners.PlayerListener;
import me.lucko.luckperms.runnables.UpdateTask;
import me.lucko.luckperms.users.BukkitUserManager;
import me.lucko.luckperms.users.UserManager;
import me.lucko.luckperms.utils.LPConfiguration;
import net.milkbowl.vault.permission.Permission;
import org.bukkit.Bukkit;
import org.bukkit.command.PluginCommand;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.ServicePriority;
import org.bukkit.plugin.java.JavaPlugin;
import java.util.Arrays;
import java.util.UUID;
@Getter
public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
public static final String VERSION = "v1.0";
private LPConfiguration configuration;
private UserManager userManager;
private GroupManager groupManager;
private Datastore datastore;
@Override
public void onEnable() {
configuration = new BukkitConfig(this);
// register events
PluginManager pm = Bukkit.getPluginManager();
pm.registerEvents(new PlayerListener(this), this);
// register commands
CommandManagerBukkit commandManager = new CommandManagerBukkit(this);
PluginCommand main = getServer().getPluginCommand("luckperms");
main.setExecutor(commandManager);
main.setAliases(Arrays.asList("perms", "lp", "permissions", "p", "perm"));
datastore = new HikariDatastore(this);
datastore.init(new DatastoreConfiguration(
configuration.getDatabaseValue("address"),
configuration.getDatabaseValue("database"),
configuration.getDatabaseValue("username"),
configuration.getDatabaseValue("password")
));
userManager = new BukkitUserManager(this);
groupManager = new GroupManager(this);
int mins = getConfiguration().getSyncTime();
if (mins > 0) {
long ticks = mins * 60 * 20;
new UpdateTask(this).runTaskTimer(this, ticks, ticks);
}
// Provide vault support
try {
if (getServer().getPluginManager().isPluginEnabled("Vault")) {
getServer().getServicesManager().register(Permission.class, new VaultHook(this), this, ServicePriority.High);
getLogger().info("Registered Vault permission hook.");
} else {
getLogger().info("Vault not found.");
}
} catch (Exception e) {
getLogger().warning("Error whilst hooking into Vault.");
e.printStackTrace();
}
}
@Override
public void doAsync(Runnable r) {
Bukkit.getScheduler().runTaskAsynchronously(this, r);
}
@Override
public void doSync(Runnable r) {
Bukkit.getScheduler().runTask(this, r);
}
@Override
public String getVersion() {
return VERSION;
}
@Override
public String getPlayerStatus(UUID uuid) {
if (getServer().getPlayer(uuid) != null) return "&aOnline";
return "&cOffline";
}
@Override
public int getPlayerCount() {
return getServer().getOnlinePlayers().size();
}
@Override
public void runUpdateTask() {
new UpdateTask(this).runTask(this);
}
}

View File

@ -0,0 +1,150 @@
package me.lucko.luckperms;
import lombok.AllArgsConstructor;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksPermissionException;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.users.User;
import net.milkbowl.vault.permission.Permission;
@AllArgsConstructor
public class VaultHook extends Permission {
private final LPBukkitPlugin plugin;
@Override
public String getName() {
return "LuckPerms";
}
@Override
public boolean isEnabled() {
return plugin.getDatastore().isAcceptingLogins();
}
@Override
public boolean hasSuperPermsCompat() {
// Idk???
return true;
}
@Override
public boolean playerHas(String world, String player, String permission) {
final User user = plugin.getUserManager().getUser(player);
return user != null && user.hasPermission(permission, true);
}
@Override
public boolean playerAdd(String world, String player, String permission) {
final User user = plugin.getUserManager().getUser(player);
if (user == null) return false;
try {
user.setPermission(permission, true);
} catch (ObjectAlreadyHasException ignored) {}
plugin.getUserManager().saveUser(user, plugin.getDatastore());
return true;
}
@Override
public boolean playerRemove(String world, String player, String permission) {
final User user = plugin.getUserManager().getUser(player);
if (user == null) return false;
try {
user.unsetPermission(permission);
} catch (ObjectLacksPermissionException ignored) {}
plugin.getUserManager().saveUser(user, plugin.getDatastore());
return true;
}
@Override
public boolean groupHas(String world, String groupName, String permission) {
final Group group = plugin.getGroupManager().getGroup(groupName);
return group != null && group.hasPermission(permission, true);
}
@Override
public boolean groupAdd(String world, String groupName, String permission) {
final Group group = plugin.getGroupManager().getGroup(groupName);
if (group == null) return false;
try {
group.setPermission(permission, true);
} catch (ObjectAlreadyHasException ignored) {}
plugin.runUpdateTask();
return true;
}
@Override
public boolean groupRemove(String world, String groupName, String permission) {
final Group group = plugin.getGroupManager().getGroup(groupName);
if (group == null) return false;
try {
group.unsetPermission(permission);
} catch (ObjectLacksPermissionException ignored) {}
plugin.runUpdateTask();
return true;
}
@Override
public boolean playerInGroup(String world, String player, String group) {
final User user = plugin.getUserManager().getUser(player);
if (user == null) return false;
return user.getGroupNames().contains(group);
}
@Override
public boolean playerAddGroup(String world, String player, String groupName) {
final User user = plugin.getUserManager().getUser(player);
if (user == null) return false;
final Group group = plugin.getGroupManager().getGroup(groupName);
if (group == null) return false;
try {
user.addGroup(group);
} catch (ObjectAlreadyHasException ignored) {}
plugin.getUserManager().saveUser(user, plugin.getDatastore());
return true;
}
@Override
public boolean playerRemoveGroup(String world, String player, String groupName) {
final User user = plugin.getUserManager().getUser(player);
if (user == null) return false;
final Group group = plugin.getGroupManager().getGroup(groupName);
if (group == null) return false;
try {
user.removeGroup(group);
} catch (ObjectLacksPermissionException ignored) {}
plugin.getUserManager().saveUser(user, plugin.getDatastore());
return true;
}
@Override
public String[] getPlayerGroups(String world, String player) {
final User user = plugin.getUserManager().getUser(player);
if (user == null) return new String[0];
return user.getGroupNames().toArray(new String[0]);
}
@Override
public String getPrimaryGroup(String world, String player) {
throw new UnsupportedOperationException();
}
@Override
public String[] getGroups() {
return plugin.getGroupManager().getGroups().keySet().toArray(new String[0]);
}
@Override
public boolean hasGroupSupport() {
return true;
}
}

View File

@ -0,0 +1,75 @@
package me.lucko.luckperms.listeners;
import lombok.AllArgsConstructor;
import me.lucko.luckperms.LPBukkitPlugin;
import me.lucko.luckperms.users.BukkitUser;
import me.lucko.luckperms.users.User;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.player.PlayerQuitEvent;
@AllArgsConstructor
public class PlayerListener implements Listener {
private final LPBukkitPlugin plugin;
@EventHandler
public void onPlayerPreLogin(AsyncPlayerPreLoginEvent e) {
if (!plugin.getDatastore().isAcceptingLogins()) {
e.disallow(AsyncPlayerPreLoginEvent.Result.KICK_OTHER, color(plugin.getConfiguration().getPrefix() +
"&cError whilst validating login with the network. \nPlease contact an administrator."));
return;
}
plugin.getDatastore().loadOrCreateUser(e.getUniqueId(), e.getName());
}
@EventHandler
public void onPlayerLogin(PlayerLoginEvent e) {
Player player = e.getPlayer();
User user = plugin.getUserManager().getUser(player.getUniqueId());
if (user == null) {
e.disallow(PlayerLoginEvent.Result.KICK_OTHER, color(plugin.getConfiguration().getPrefix() +
"&cUser data could not be loaded. Please contact an administrator."));
return;
}
if (user instanceof BukkitUser) {
BukkitUser u = (BukkitUser) user;
u.setAttachment(player.addAttachment(plugin));
}
user.refreshPermissions();
}
@EventHandler
public void onPlayerJoin(PlayerJoinEvent e) {
// Save UUID data for the player
plugin.getDatastore().saveUUIDData(e.getPlayer().getName(), e.getPlayer().getUniqueId(), success -> {});
User user = plugin.getUserManager().getUser(e.getPlayer().getUniqueId());
if (user != null) {
// Refresh permissions again
user.refreshPermissions();
}
}
@EventHandler
public void onPlayerQuit(PlayerQuitEvent e) {
Player player = e.getPlayer();
// Unload the user from memory when they disconnect
User user = plugin.getUserManager().getUser(player.getUniqueId());
plugin.getUserManager().unloadUser(user);
}
public static String color(String string) {
return ChatColor.translateAlternateColorCodes('&', string);
}
}

View File

@ -0,0 +1,25 @@
package me.lucko.luckperms.runnables;
import lombok.AllArgsConstructor;
import me.lucko.luckperms.LPBukkitPlugin;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
@AllArgsConstructor
public class UpdateTask extends BukkitRunnable {
private final LPBukkitPlugin plugin;
@Override
public void run() {
plugin.getLogger().info("Running update task.");
// Re-load all of the groups
plugin.getGroupManager().loadAllGroups();
// Refresh all online users.
for (Player p : Bukkit.getOnlinePlayers()) {
plugin.getDatastore().loadUser(p.getUniqueId(), success -> {});
}
}
}

View File

@ -0,0 +1,52 @@
package me.lucko.luckperms.users;
import lombok.Getter;
import lombok.Setter;
import me.lucko.luckperms.LPBukkitPlugin;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.permissions.PermissionAttachment;
import java.util.Map;
import java.util.UUID;
public class BukkitUser extends User {
private final LPBukkitPlugin plugin;
@Getter
@Setter
private PermissionAttachment attachment = null;
public BukkitUser(UUID uuid, LPBukkitPlugin plugin) {
super(uuid, plugin);
this.plugin = plugin;
}
public BukkitUser(UUID uuid, String username, LPBukkitPlugin plugin) {
super(uuid, username, plugin);
this.plugin = plugin;
}
@Override
public void refreshPermissions() {
Player player = Bukkit.getPlayer(getUuid());
if (player == null) return;
if (attachment == null) {
getPlugin().getLogger().warning("User " + getName() + " does not have a permissions attachment defined.");
setAttachment(player.addAttachment(plugin));
}
// Clear existing permissions
for (String p : attachment.getPermissions().keySet()) {
attachment.setPermission(p, false);
}
// Re-add all defined permissions for the user
Map<String, Boolean> local = getLocalPermissions(getPlugin().getConfiguration().getServer(), null);
for (String node : local.keySet()) {
attachment.setPermission(node, local.get(node));
}
}
}

View File

@ -0,0 +1,53 @@
package me.lucko.luckperms.users;
import me.lucko.luckperms.LPBukkitPlugin;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import java.util.UUID;
public class BukkitUserManager extends UserManager {
private final LPBukkitPlugin plugin;
public BukkitUserManager(LPBukkitPlugin plugin) {
this.plugin = plugin;
}
@Override
public void unloadUser(User user) {
if (user != null) {
if (user instanceof BukkitUser) {
BukkitUser u = (BukkitUser) user;
if (u.getAttachment() != null) {
Player player = Bukkit.getPlayer(u.getUuid());
if (player != null) {
player.removeAttachment(u.getAttachment());
}
u.setAttachment(null);
}
}
getUsers().remove(user.getUuid());
}
}
@Override
public void cleanupUser(User user) {
if (Bukkit.getPlayer(user.getUuid()) == null) {
unloadUser(user);
}
}
@Override
public User makeUser(UUID uuid) {
return new BukkitUser(uuid, plugin);
}
@Override
public User makeUser(UUID uuid, String username) {
return new BukkitUser(uuid, username, plugin);
}
}

View File

@ -0,0 +1,19 @@
# LuckPerms Configuration
# The name of the server, used for server specific permissions. Set to 'global' to disable.
server: global
# The default group assigned to all user on join. e.g. a value of "default" = luckperms.group.default
default-group: default
# If users on this server should have their global permissions/groups applied.
include-global: true
prefix: '&7&l[&b&lL&a&lP&7&l] &c'
sql:
address: localhost:3306
database: minecraft
username: root
password: ''
sync-minutes: 3

View File

@ -0,0 +1,10 @@
name: LuckPerms
author: Luck
version: 1.0
main: me.lucko.luckperms.LPBukkitPlugin
softdepend: [Vault]
description: A permissions plugin
commands:
luckperms:
description: Manage permissions
aliases: [perms, permissions, lp, p, perm]

74
bungee/pom.xml Normal file
View File

@ -0,0 +1,74 @@
<?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</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>luckperms-bungee</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>LuckPerms</name>
<build>
<defaultGoal>clean package</defaultGoal>
<finalName>LuckPerms</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.2</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.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<minimizeJar>true</minimizeJar>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<!-- BungeeCord API -->
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
<version>1.9-SNAPSHOT</version>
<type>jar</type>
<scope>provided</scope>
</dependency>
<!-- LuckPerms Common -->
<dependency>
<groupId>me.lucko</groupId>
<artifactId>luckperms-common</artifactId>
<version>${project.parent.version}</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,78 @@
package me.lucko.luckperms;
import me.lucko.luckperms.utils.LPConfiguration;
import net.md_5.bungee.config.Configuration;
import net.md_5.bungee.config.ConfigurationProvider;
import net.md_5.bungee.config.YamlConfiguration;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
public class BungeeConfig implements LPConfiguration {
private final LPBungeePlugin plugin;
private Configuration configuration;
public BungeeConfig(LPBungeePlugin plugin) {
this.plugin = plugin;
reload();
}
private void reload() {
try {
configuration = ConfigurationProvider.getProvider(YamlConfiguration.class).load(makeFile("config.yml"));
} catch (IOException e) {
e.printStackTrace();
}
}
private File makeFile(String file) throws IOException {
File cfg = new File(plugin.getDataFolder(), file);
if (!cfg.exists()) {
plugin.getDataFolder().mkdir();
try (InputStream is = plugin.getResourceAsStream(file)) {
Files.copy(is, cfg.toPath());
}
}
return cfg;
}
@Override
public String getServer() {
return configuration.getString("server");
}
@Override
public String getPrefix() {
return configuration.getString("prefix");
}
@Override
public int getSyncTime() {
return configuration.getInt("sql.sync-minutes");
}
@Override
public String getDefaultGroupNode() {
return "luckperms.group." + configuration.getString("default-group");
}
@Override
public String getDefaultGroupName() {
return configuration.getString("default-group");
}
@Override
public boolean getIncludeGlobalPerms() {
return configuration.getBoolean("include-global");
}
@Override
public String getDatabaseValue(String value) {
return configuration.getString("sql." + value);
}
}

View File

@ -0,0 +1,112 @@
package me.lucko.luckperms;
import lombok.Getter;
import me.lucko.luckperms.commands.CommandManager;
import me.lucko.luckperms.data.Datastore;
import me.lucko.luckperms.data.DatastoreConfiguration;
import me.lucko.luckperms.data.HikariDatastore;
import me.lucko.luckperms.groups.GroupManager;
import me.lucko.luckperms.listeners.PlayerListener;
import me.lucko.luckperms.runnables.UpdateTask;
import me.lucko.luckperms.users.BungeeUserManager;
import me.lucko.luckperms.users.UserManager;
import me.lucko.luckperms.utils.LPConfiguration;
import net.md_5.bungee.api.plugin.Plugin;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
public static final String VERSION = "v1.0";
@Getter
LPConfiguration configuration;
@Getter
UserManager userManager;
@Getter
GroupManager groupManager;
@Getter
Datastore datastore;
@Override
public void onEnable() {
configuration = new BungeeConfig(this);
// register events
getProxy().getPluginManager().registerListener(this, new PlayerListener(this));
// register commands
getProxy().getPluginManager().registerCommand(this, new MainCommand(new CommandManager(this)));
datastore = new HikariDatastore(this);
datastore.init(new DatastoreConfiguration(
configuration.getDatabaseValue("address"),
configuration.getDatabaseValue("database"),
configuration.getDatabaseValue("username"),
configuration.getDatabaseValue("password")
));
userManager = new BungeeUserManager(this);
groupManager = new GroupManager(this);
int mins = getConfiguration().getSyncTime();
if (mins > 0) {
getProxy().getScheduler().schedule(this, new UpdateTask(this), mins, mins, TimeUnit.MINUTES);
}
}
@Override
public UserManager getUserManager() {
return userManager;
}
@Override
public GroupManager getGroupManager() {
return groupManager;
}
@Override
public String getVersion() {
return VERSION;
}
@Override
public String getPlayerStatus(UUID uuid) {
if (getProxy().getPlayer(uuid) != null) return "&aOnline";
return "&cOffline";
}
@Override
public int getPlayerCount() {
return getProxy().getOnlineCount();
}
@Override
public LPConfiguration getConfiguration() {
return configuration;
}
@Override
public Datastore getDatastore() {
return datastore;
}
@Override
public void runUpdateTask() {
new UpdateTask(this).run();
}
@Override
public void doAsync(Runnable r) {
getProxy().getScheduler().runAsync(this, r);
}
@Override
public void doSync(Runnable r) {
r.run();
}
}

View File

@ -0,0 +1,34 @@
package me.lucko.luckperms;
import me.lucko.luckperms.commands.CommandManager;
import me.lucko.luckperms.commands.Sender;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.plugin.Command;
import java.util.Arrays;
public class MainCommand extends Command {
private final CommandManager manager;
public MainCommand(CommandManager manager) {
super("luckpermsbungee", "luckperms.use", "bperms", "lpb", "bpermissions", "bp", "bperm");
this.manager = manager;
}
@Override
public void execute(CommandSender sender, String[] args) {
manager.onCommand(new Sender() {
@Override
public void sendMessage(String s) {
sender.sendMessage(new TextComponent(s));
}
@Override
public boolean hasPermission(String node) {
return sender.hasPermission(node);
}
}, Arrays.asList(args));
}
}

View File

@ -0,0 +1,44 @@
package me.lucko.luckperms.listeners;
import lombok.AllArgsConstructor;
import me.lucko.luckperms.LPBungeePlugin;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.data.Datastore;
import me.lucko.luckperms.users.User;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.PlayerDisconnectEvent;
import net.md_5.bungee.api.event.PostLoginEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.event.EventHandler;
@AllArgsConstructor
public class PlayerListener implements Listener {
private final LPBungeePlugin plugin;
@EventHandler
public void onPlayerPostLogin(PostLoginEvent e) {
final ProxiedPlayer player = e.getPlayer();
plugin.getDatastore().loadOrCreateUser(player.getUniqueId(), player.getName(), success -> {
if (!success) {
e.getPlayer().sendMessage(new TextComponent(Util.color("&e&l[LP] &cPermissions data could not be loaded. Please contact an administrator.")));
} else {
User user = plugin.getUserManager().getUser(player.getUniqueId());
user.refreshPermissions();
}
});
plugin.getDatastore().saveUUIDData(e.getPlayer().getName(), e.getPlayer().getUniqueId(), success -> {});
}
@EventHandler
public void onPlayerQuit(PlayerDisconnectEvent e) {
ProxiedPlayer player = e.getPlayer();
// Unload the user from memory when they disconnect
User user = plugin.getUserManager().getUser(player.getUniqueId());
plugin.getUserManager().unloadUser(user);
}
}

View File

@ -0,0 +1,23 @@
package me.lucko.luckperms.runnables;
import lombok.AllArgsConstructor;
import me.lucko.luckperms.LPBungeePlugin;
import net.md_5.bungee.api.connection.ProxiedPlayer;
@AllArgsConstructor
public class UpdateTask implements Runnable {
private final LPBungeePlugin plugin;
@Override
public void run() {
plugin.getLogger().info("Running update task.");
// Re-load all of the groups
plugin.getGroupManager().loadAllGroups();
// Refresh all online users.
for (ProxiedPlayer p : plugin.getProxy().getPlayers()) {
plugin.getDatastore().loadUser(p.getUniqueId(), success -> {});
}
}
}

View File

@ -0,0 +1,42 @@
package me.lucko.luckperms.users;
import me.lucko.luckperms.LPBungeePlugin;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import java.util.UUID;
public class BungeeUser extends User {
private final LPBungeePlugin plugin;
public BungeeUser(UUID uuid, LPBungeePlugin plugin) {
super(uuid, plugin);
this.plugin = plugin;
}
public BungeeUser(UUID uuid, String username, LPBungeePlugin plugin) {
super(uuid, username, plugin);
this.plugin = plugin;
}
@Override
public void refreshPermissions() {
ProxiedPlayer player = plugin.getProxy().getPlayer(getUuid());
if (player == null) return;
// Clear existing permissions
Collection<String> perms = new ArrayList<>(player.getPermissions());
for (String p : perms) {
player.setPermission(p, false);
}
// Re-add all defined permissions for the user
Map<String, Boolean> local = getLocalPermissions(getPlugin().getConfiguration().getServer(), null);
for (String node : local.keySet()) {
player.setPermission(node, local.get(node));
}
}
}

View File

@ -0,0 +1,44 @@
package me.lucko.luckperms.users;
import me.lucko.luckperms.LPBungeePlugin;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.util.UUID;
public class BungeeUserManager extends UserManager {
private final LPBungeePlugin plugin;
public BungeeUserManager(LPBungeePlugin plugin) {
this.plugin = plugin;
}
@Override
public void unloadUser(User user) {
if (user != null) {
ProxiedPlayer player = plugin.getProxy().getPlayer(user.getUuid());
if (player != null) {
player.getPermissions().clear();
}
getUsers().remove(user.getUuid());
}
}
@Override
public void cleanupUser(User user) {
if (plugin.getProxy().getPlayer(user.getUuid()) == null) {
unloadUser(user);
}
}
@Override
public User makeUser(UUID uuid) {
return new BungeeUser(uuid, plugin);
}
@Override
public User makeUser(UUID uuid, String username) {
return new BungeeUser(uuid, username, plugin);
}
}

View File

@ -0,0 +1,19 @@
# LuckPerms Configuration
# The name of the server, used for server specific permissions. Set to 'global' to disable.
server: bungee
# The default group assigned to all user on join. e.g. a value of "default" = luckperms.group.default
default-group: default
# If users on this server should have their global permissions/groups applied.
include-global: false
prefix: '&7&l[&b&lL&a&lP&7&l] &c'
sql:
address: localhost:3306
database: minecraft
username: root
password: ''
sync-minutes: 3

View File

@ -0,0 +1,3 @@
name: LuckPerms
main: me.lucko.luckperms.LPBungeePlugin
author: Luck

26
common/pom.xml Normal file
View File

@ -0,0 +1,26 @@
<?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</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>luckperms-common</artifactId>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,77 @@
package me.lucko.luckperms;
import me.lucko.luckperms.data.Datastore;
import me.lucko.luckperms.groups.GroupManager;
import me.lucko.luckperms.users.UserManager;
import me.lucko.luckperms.utils.LPConfiguration;
import java.util.UUID;
import java.util.logging.Logger;
public interface LuckPermsPlugin {
/**
* Retrieves the {@link UserManager} used to manage users and their permissions/groups
* @return the {@link UserManager} object
*/
UserManager getUserManager();
/**
* Retrieves the {@link GroupManager} used to manage the loaded groups and modify their permissions
* @return the {@link GroupManager} object
*/
GroupManager getGroupManager();
/**
* Retrieves the {@link LPConfiguration} for getting values from the config
* @return the {@link LPConfiguration} implementation for the platform
*/
LPConfiguration getConfiguration();
/**
* Retrieves the {@link Datastore} for loading/saving plugin data
* @return the {@link Datastore} object
*/
Datastore getDatastore();
/**
* Retrieves the {@link Logger} for the plugin
* @return the plugin's {@link Logger}
*/
Logger getLogger();
/**
* @return the version of the plugin
*/
String getVersion();
/**
* Returns a colored string indicating the status of a player
* @param uuid The player's uuid
* @return a formatted status string
*/
String getPlayerStatus(UUID uuid);
/**
* Gets the number of users online on the platform
* @return the number of users
*/
int getPlayerCount();
/**
* Runs an update task
*/
void runUpdateTask();
/**
* Execute a runnable asynchronously
* @param r the task to run
*/
void doAsync(Runnable r);
/**
* Execute a runnable synchronously
* @param r the task to run
*/
void doSync(Runnable r);
}

View File

@ -0,0 +1,113 @@
package me.lucko.luckperms.commands;
import lombok.Getter;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.group.CreateGroupCommand;
import me.lucko.luckperms.commands.group.DeleteGroupCommand;
import me.lucko.luckperms.commands.group.GroupMainCommand;
import me.lucko.luckperms.commands.group.ListGroupsCommand;
import me.lucko.luckperms.commands.group.subcommands.*;
import me.lucko.luckperms.commands.misc.DebugCommand;
import me.lucko.luckperms.commands.misc.InfoCommand;
import me.lucko.luckperms.commands.misc.SyncCommand;
import me.lucko.luckperms.commands.user.UserMainCommand;
import me.lucko.luckperms.commands.user.subcommands.*;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
public class CommandManager {
private final LuckPermsPlugin plugin;
@Getter
private final List<MainCommand> mainCommands = new ArrayList<>();
public CommandManager(LuckPermsPlugin plugin) {
this.plugin = plugin;
UserMainCommand userCommand = new UserMainCommand();
this.registerMainCommand(userCommand);
userCommand.registerSubCommand(new UserAddGroupCommand());
userCommand.registerSubCommand(new UserClearCommand());
userCommand.registerSubCommand(new UserGetUUIDCommand());
userCommand.registerSubCommand(new UserHasPermCommand());
userCommand.registerSubCommand(new UserInfoCommand());
userCommand.registerSubCommand(new UserListNodesCommand());
userCommand.registerSubCommand(new UserRemoveGroupCommand());
userCommand.registerSubCommand(new UserSetPermissionCommand());
userCommand.registerSubCommand(new UserUnSetPermissionCommand());
GroupMainCommand groupCommand = new GroupMainCommand();
this.registerMainCommand(groupCommand);
groupCommand.registerSubCommand(new GroupClearCommand());
groupCommand.registerSubCommand(new GroupHasPermCommand());
groupCommand.registerSubCommand(new GroupInfoCommand());
groupCommand.registerSubCommand(new GroupListNodesCommand());
groupCommand.registerSubCommand(new GroupSetInheritCommand());
groupCommand.registerSubCommand(new GroupSetPermissionCommand());
groupCommand.registerSubCommand(new GroupUnsetInheritCommand());
groupCommand.registerSubCommand(new GroupUnSetPermissionCommand());
this.registerMainCommand(new CreateGroupCommand());
this.registerMainCommand(new DeleteGroupCommand());
this.registerMainCommand(new ListGroupsCommand());
this.registerMainCommand(new DebugCommand());
this.registerMainCommand(new InfoCommand());
this.registerMainCommand(new SyncCommand());
}
/**
* Generic on command method to be called from the command executor object of the platform
* @param sender who sent the command
* @param args the arguments provided
* @return if the command was successful (hint: it always is :> )
*/
public boolean onCommand(Sender sender, List<String> args) {
if (args.size() == 0) {
Util.sendPluginMessage(sender, "&6Running &bLuckPerms " + plugin.getVersion() + "&6.");
if (sender.hasPermission("luckperms.info")) {
for (MainCommand c : mainCommands) {
Util.sendPluginMessage(sender, "&e-> &d" + c.getUsage());
}
}
} else {
String c = args.get(0);
MainCommand main = null;
for (MainCommand mainCommand : mainCommands) {
if (mainCommand.getName().equalsIgnoreCase(c)) {
main = mainCommand;
break;
}
}
if (main == null) {
Util.sendPluginMessage(sender, "Command not recognised.");
return true;
}
if (main.getRequiredArgsLength() == 0) {
main.execute(plugin, sender, null);
return true;
}
if (args.size() == 1) {
main.sendUsage(sender);
return true;
}
main.execute(plugin, sender, new ArrayList<>(args.subList(1, args.size())));
}
return true;
}
public void registerMainCommand(MainCommand command) {
plugin.getLogger().log(Level.INFO, "[CommandManager] Registered main command '" + command.getName() + "'");
mainCommands.add(command);
}
}

View File

@ -0,0 +1,42 @@
package me.lucko.luckperms.commands;
import lombok.Getter;
import me.lucko.luckperms.LuckPermsPlugin;
import java.util.List;
import java.util.stream.Collectors;
public abstract class MainCommand {
@Getter
private final String name;
@Getter
private final String usage;
@Getter
private final int requiredArgsLength;
public MainCommand(String name, String usage, int requiredArgsLength) {
this.name = name;
this.usage = usage;
this.requiredArgsLength = requiredArgsLength;
}
protected abstract void execute(LuckPermsPlugin plugin, Sender sender, List<String> args);
public abstract List<? extends SubCommand> getSubCommands();
protected void sendUsage(Sender sender) {
List<SubCommand> subs = getSubCommands().stream().filter(s -> s.isAuthorized(sender)).collect(Collectors.toList());
if (subs.size() > 0) {
Util.sendPluginMessage(sender, "&e" + getName() + " Sub Commands:");
for (SubCommand s : subs) {
s.sendUsage(sender);
}
} else {
Util.sendPluginMessage(sender, "You do not have permission to use this command!");
}
}
}

View File

@ -0,0 +1,8 @@
package me.lucko.luckperms.commands;
public interface Sender {
void sendMessage(String s);
boolean hasPermission(String node);
}

View File

@ -0,0 +1,35 @@
package me.lucko.luckperms.commands;
import lombok.Getter;
public abstract class SubCommand {
@Getter
private final String name;
@Getter
private final String description;
@Getter
private final String usage;
@Getter
private final String permission;
public SubCommand(String name, String description, String usage, String permission) {
this.name = name;
this.description = description;
this.usage = usage;
this.permission = permission;
}
public boolean isAuthorized(Sender sender) {
return sender.hasPermission(permission);
}
public void sendUsage(Sender sender) {
Util.sendPluginMessage(sender, "&e-> &d" + getUsage());
}
public abstract boolean isArgLengthInvalid(int argLength);
}

View File

@ -0,0 +1,81 @@
package me.lucko.luckperms.commands;
import java.util.List;
import java.util.Map;
import java.util.UUID;
public class Util {
public static void sendPluginMessage(Sender sender, String message) {
// TODO: Pull the prefix from the config somehow
sender.sendMessage(color("&7&l[&b&lL&a&lP&7&l] &c" + message));
}
public static String color(String s) {
return translateAlternateColorCodes('&', s);
}
public static String translateAlternateColorCodes(char altColorChar, String textToTranslate) {
// Stolen from Bukkit :>
char[] b = textToTranslate.toCharArray();
for(int i = 0; i < b.length - 1; ++i) {
if(b[i] == altColorChar && "0123456789AaBbCcDdEeFfKkLlMmNnOoRr".indexOf(b[i + 1]) > -1) {
b[i] = 167;
b[i + 1] = Character.toLowerCase(b[i + 1]);
}
}
return new String(b);
}
public static void sendBoolean(Sender sender, String node, boolean b) {
if (b) {
sender.sendMessage(Util.color("&b" + node + ": &atrue"));
} else {
sender.sendMessage(Util.color("&b" + node + ": &cfalse"));
}
}
public static String listToCommaSep(List<String> strings) {
if (strings.isEmpty()) return "&6None";
StringBuilder sb = new StringBuilder();
for (String s : strings) {
sb.append("&6").append(s).append("&7, ");
}
return sb.delete(sb.length() - 2, sb.length()).toString();
}
public static String nodesToString(Map<String, Boolean> nodes) {
if (nodes.isEmpty()) return "&6None";
StringBuilder sb = new StringBuilder();
for (String node : nodes.keySet()) {
if (nodes.get(node)) {
sb.append("&a").append(node).append("&7, ");
} else {
sb.append("&c").append(node).append("&7, ");
}
}
return sb.delete(sb.length() - 2, sb.length()).toString();
}
public static UUID parseUuid(String s) {
try {
return UUID.fromString(s);
} catch (IllegalArgumentException e) {
try {
return UUID.fromString(s.replaceAll(
"(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})",
"$1-$2-$3-$4-$5"));
} catch (IllegalArgumentException e1) {
return null;
}
}
}
}

View File

@ -0,0 +1,51 @@
package me.lucko.luckperms.commands.group;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.MainCommand;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.commands.Util;
import java.util.ArrayList;
import java.util.List;
public class CreateGroupCommand extends MainCommand {
public CreateGroupCommand() {
super("CreateGroup", "/perms creategroup <group>", 1);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, List<String> args) {
if (!sender.hasPermission("luckperms.creategroup")) {
Util.sendPluginMessage(sender, "You do not have permission to use this command!");
return;
}
if (args.size() == 0) {
sendUsage(sender);
return;
}
String groupName = args.get(0).toLowerCase();
plugin.getDatastore().loadGroup(groupName, success -> {
if (success) {
Util.sendPluginMessage(sender, "That group already exists!");
} else {
plugin.getDatastore().createAndLoadGroup(groupName, success1 -> {
if (!success1) {
Util.sendPluginMessage(sender, "There was an error whilst creating the group.");
} else {
Util.sendPluginMessage(sender, "&b" + groupName + "&a was successfully created.");
plugin.runUpdateTask();
}
});
}
});
}
@Override
public List<SubCommand> getSubCommands() {
return new ArrayList<>();
}
}

View File

@ -0,0 +1,63 @@
package me.lucko.luckperms.commands.group;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.MainCommand;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.groups.Group;
import java.util.ArrayList;
import java.util.List;
public class DeleteGroupCommand extends MainCommand {
public DeleteGroupCommand() {
super("DeleteGroup", "/perms deletegroup <group>", 1);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, List<String> args) {
if (!sender.hasPermission("luckperms.deletegroup")) {
Util.sendPluginMessage(sender, "You do not have permission to use this command!");
return;
}
if (args.size() == 0) {
sendUsage(sender);
return;
}
String groupName = args.get(0).toLowerCase();
if (groupName.equalsIgnoreCase(plugin.getConfiguration().getDefaultGroupName())) {
Util.sendPluginMessage(sender, "You cannot delete the default group.");
return;
}
plugin.getDatastore().loadGroup(groupName, success -> {
if (!success) {
Util.sendPluginMessage(sender, "That group does not exist!");
} else {
Group group = plugin.getGroupManager().getGroup(groupName);
if (group == null) {
Util.sendPluginMessage(sender, "An unexpected error occurred.");
} else {
plugin.getDatastore().deleteGroup(group, success1 -> {
if (!success1) {
Util.sendPluginMessage(sender, "There was an error whilst creating the group.");
} else {
Util.sendPluginMessage(sender, "&b" + groupName + "&a was successfully deleted.");
plugin.runUpdateTask();
}
});
}
}
});
}
@Override
public List<SubCommand> getSubCommands() {
return new ArrayList<>();
}
}

View File

@ -0,0 +1,103 @@
package me.lucko.luckperms.commands.group;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.MainCommand;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.groups.Group;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class GroupMainCommand extends MainCommand {
private final List<GroupSubCommand> subCommands = new ArrayList<>();
public GroupMainCommand() {
super("Group", "/perms group <group>", 2);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, List<String> args) {
if (args.size() <= 1) {
sendUsage(sender);
return;
}
List<String> strippedArgs = new ArrayList<>();
if (args.size() > 2) {
strippedArgs.addAll(args.subList(2, args.size()));
}
String c = args.get(1);
GroupSubCommand tempSub = null;
for (GroupSubCommand s : subCommands) {
if (s.getName().equalsIgnoreCase(c)) {
tempSub = s;
break;
}
}
final GroupSubCommand sub = tempSub;
if (sub == null) {
Util.sendPluginMessage(sender, "Command not recognised.");
return;
}
if (!sub.isAuthorized(sender)) {
Util.sendPluginMessage(sender, "You do not have permission to use this command!");
return;
}
String g = args.get(0).toLowerCase();
plugin.getDatastore().loadGroup(g, success -> {
if (!success) {
Util.sendPluginMessage(sender, "&eGroup could not be found.");
return;
}
Group group = plugin.getGroupManager().getGroup(g);
if (group == null) {
Util.sendPluginMessage(sender, "&eGroup could not be found.");
return;
}
if (sub.isArgLengthInvalid(strippedArgs.size())) {
sub.sendUsage(sender);
return;
}
sub.execute(plugin, sender, group, strippedArgs);
});
}
@Override
public List<? extends SubCommand> getSubCommands() {
return subCommands;
}
public void registerSubCommand(GroupSubCommand subCommand) {
subCommands.add(subCommand);
}
@Override
protected void sendUsage(Sender sender) {
List<SubCommand> subs = getSubCommands().stream().filter(s -> s.isAuthorized(sender)).collect(Collectors.toList());
if (subs.size() > 0) {
Util.sendPluginMessage(sender, "&e" + getName() + " Sub Commands:");
for (SubCommand s : subs) {
s.sendUsage(sender);
}
} else {
Util.sendPluginMessage(sender, "You do not have permission to use this command!");
}
}
}

View File

@ -0,0 +1,29 @@
package me.lucko.luckperms.commands.group;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.groups.Group;
import java.util.List;
public abstract class GroupSubCommand extends SubCommand {
public GroupSubCommand(String name, String description, String usage, String permission) {
super(name, description, usage, permission);
}
protected abstract void execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args);
protected void saveGroup(Group group, Sender sender, LuckPermsPlugin plugin) {
plugin.getDatastore().saveGroup(group, success -> {
if (success) {
Util.sendPluginMessage(sender, "&7(Group data was saved to the datastore)");
} else {
Util.sendPluginMessage(sender, "There was an error whilst saving the group.");
}
plugin.runUpdateTask();
});
}
}

View File

@ -0,0 +1,37 @@
package me.lucko.luckperms.commands.group;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.MainCommand;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.commands.Util;
import java.util.ArrayList;
import java.util.List;
public class ListGroupsCommand extends MainCommand {
public ListGroupsCommand() {
super("ListGroups", "/perms listgroups", 0);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, List<String> args) {
if (!sender.hasPermission("luckperms.listgroups")) {
Util.sendPluginMessage(sender, "You do not have permission to use this command!");
return;
}
plugin.getDatastore().loadAllGroups(success -> {
if (!success) {
Util.sendPluginMessage(sender, "Unable to load all groups.");
} else {
Util.sendPluginMessage(sender, "&aGroups: " + Util.listToCommaSep(new ArrayList<>(plugin.getGroupManager().getGroups().keySet())));
}
});
}
@Override
public List<SubCommand> getSubCommands() {
return null;
}
}

View File

@ -0,0 +1,29 @@
package me.lucko.luckperms.commands.group.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.group.GroupSubCommand;
import me.lucko.luckperms.groups.Group;
import java.util.List;
public class GroupClearCommand extends GroupSubCommand {
public GroupClearCommand() {
super("clear", "Clears a groups permissions",
"/perms group <group> clear", "luckperms.group.clear");
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args) {
group.clearNodes();
Util.sendPluginMessage(sender, "&b" + group.getName() + "&a's permissions were cleared.");
saveGroup(group, sender, plugin);
}
@Override
public boolean isArgLengthInvalid(int argLength) {
return true;
}
}

View File

@ -0,0 +1,30 @@
package me.lucko.luckperms.commands.group.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.group.GroupSubCommand;
import me.lucko.luckperms.groups.Group;
import java.util.List;
public class GroupHasPermCommand extends GroupSubCommand {
public GroupHasPermCommand() {
super("haspermission", "Checks to see if a group has a certain permission node",
"/perms group <group> haspermission <node> [server]", "luckperms.group.haspermission");
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args) {
if (args.size() >= 2) {
Util.sendBoolean(sender, args.get(0), group.hasPermission(args.get(0), true, args.get(1)));
} else {
Util.sendBoolean(sender, args.get(0), group.hasPermission(args.get(0), true, "global"));
}
}
@Override
public boolean isArgLengthInvalid(int argLength) {
return argLength == 0;
}
}

View File

@ -0,0 +1,31 @@
package me.lucko.luckperms.commands.group.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.group.GroupSubCommand;
import me.lucko.luckperms.groups.Group;
import java.util.List;
public class GroupInfoCommand extends GroupSubCommand {
public GroupInfoCommand() {
super("info", "Gives info about the group",
"/perms group <group> info", "luckperms.group.info");
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args) {
final String prefix = plugin.getConfiguration().getPrefix();
String sb = prefix + "&d-> &eGroup: &6" + group.getName() + "\n" +
prefix + "&d-> &ePermissions: &6" + group.getNodes().keySet().size() + "\n" +
prefix + "&d-> &bUse &a/perms group " + group.getName() + " listnodes &bto see all permissions.";
sender.sendMessage(Util.color(sb));
}
@Override
public boolean isArgLengthInvalid(int argLength) {
return false;
}
}

View File

@ -0,0 +1,27 @@
package me.lucko.luckperms.commands.group.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.group.GroupSubCommand;
import me.lucko.luckperms.groups.Group;
import java.util.List;
public class GroupListNodesCommand extends GroupSubCommand {
public GroupListNodesCommand() {
super("listnodes", "Lists the permission nodes the group has",
"/perms group <group> listnodes", "luckperms.group.listnodes");
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args) {
Util.sendPluginMessage(sender, "&e" + group.getName() + "'s Nodes:");
sender.sendMessage(Util.color(Util.nodesToString(group.getNodes())));
}
@Override
public boolean isArgLengthInvalid(int argLength) {
return false;
}
}

View File

@ -0,0 +1,50 @@
package me.lucko.luckperms.commands.group.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.group.GroupSubCommand;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.groups.Group;
import java.util.List;
public class GroupSetInheritCommand extends GroupSubCommand {
public GroupSetInheritCommand() {
super("setinherit", "Sets another group for this group to inherit permissions from",
"/perms group <group> setinherit <group> [server]", "luckperms.group.setinherit");
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args) {
String groupName = args.get(0).toLowerCase();
plugin.getDatastore().loadGroup(groupName, success -> {
if (!success) {
Util.sendPluginMessage(sender, groupName + " does not exist!");
} else {
final String node = "luckperms.group." + groupName;
try {
if (args.size() == 2) {
final String server = args.get(1).toLowerCase();
group.setPermission(node, true, server);
Util.sendPluginMessage(sender, "&b" + group.getName() + "&a now inherits permissions from &b" + groupName + "&a on server &b" + server + "&a.");
} else {
group.setPermission(node, true);
Util.sendPluginMessage(sender, "&b" + group.getName() + "&a now inherits permissions from &b" + groupName + "&a.");
}
saveGroup(group, sender, plugin);
} catch (ObjectAlreadyHasException e) {
Util.sendPluginMessage(sender, group.getName() + " already inherits '" + groupName + "'.");
}
}
});
}
@Override
public boolean isArgLengthInvalid(int argLength) {
return argLength == 0;
}
}

View File

@ -0,0 +1,60 @@
package me.lucko.luckperms.commands.group.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.group.GroupSubCommand;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.groups.Group;
import java.util.List;
public class GroupSetPermissionCommand extends GroupSubCommand {
public GroupSetPermissionCommand() {
super("set", "Sets a permission for a group",
"/perms group <group> set <node> <true|false> [server]", "luckperms.group.setpermission");
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args) {
String node = args.get(0);
String bool = args.get(1);
if (node.contains("/")) {
sendUsage(sender);
return;
}
if (node.matches(".*luckperms\\.group\\..*")) {
Util.sendPluginMessage(sender, "Use the inherit command instead of specifying the node.");
return;
}
if (!bool.equalsIgnoreCase("true") && !bool.equalsIgnoreCase("false")) {
sendUsage(sender);
return;
}
boolean b = Boolean.parseBoolean(bool);
try {
if (args.size() == 3) {
final String server = args.get(2).toLowerCase();
group.setPermission(node, b, server);
Util.sendPluginMessage(sender, "&aSet &b" + node + "&a to &b" + bool + "&a for &b" + group.getName() + "&a on server &b" + server + "&a.");
} else {
group.setPermission(node, b);
Util.sendPluginMessage(sender, "&aSet &b" + node + "&a to " + bool + " for &b" + group.getName() + "&a.");
}
saveGroup(group, sender, plugin);
} catch (ObjectAlreadyHasException e) {
Util.sendPluginMessage(sender, group.getName() + " already has this permission!");
}
}
@Override
public boolean isArgLengthInvalid(int argLength) {
return argLength < 2;
}
}

View File

@ -0,0 +1,52 @@
package me.lucko.luckperms.commands.group.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.group.GroupSubCommand;
import me.lucko.luckperms.exceptions.ObjectLacksPermissionException;
import me.lucko.luckperms.groups.Group;
import java.util.List;
public class GroupUnSetPermissionCommand extends GroupSubCommand {
public GroupUnSetPermissionCommand() {
super("unset", "Unsets a permission for a group",
"/perms group <group> unset <node> [server]", "luckperms.group.unsetpermission");
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args) {
String node = args.get(0);
if (node.contains("/")) {
sendUsage(sender);
return;
}
if (node.matches(".*luckperms\\.group\\..*")) {
Util.sendPluginMessage(sender, "Use the uninherit command instead of specifying the node.");
return;
}
try {
if (args.size() == 2) {
final String server = args.get(1).toLowerCase();
group.unsetPermission(node, server);
Util.sendPluginMessage(sender, "&aUnset &b" + node + "&a for &b" + group.getName() + "&a on server &b" + server + "&a.");
} else {
group.unsetPermission(node);
Util.sendPluginMessage(sender, "&aUnset &b" + node + "&a for &b" + group.getName() + "&a.");
}
saveGroup(group, sender, plugin);
} catch (ObjectLacksPermissionException e) {
Util.sendPluginMessage(sender, "That group does not have this permission set.");
}
}
@Override
public boolean isArgLengthInvalid(int argLength) {
return argLength == 0;
}
}

View File

@ -0,0 +1,42 @@
package me.lucko.luckperms.commands.group.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.group.GroupSubCommand;
import me.lucko.luckperms.exceptions.ObjectLacksPermissionException;
import me.lucko.luckperms.groups.Group;
import java.util.List;
public class GroupUnsetInheritCommand extends GroupSubCommand {
public GroupUnsetInheritCommand() {
super("unsetinherit", "Unsets another group for this group to inherit permissions from",
"/perms group <group> unsetinherit <group> [server]", "luckperms.group.unsetinherit");
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args) {
String groupName = args.get(0).toLowerCase();
String server;
if (args.size() == 2) {
server = args.get(1).toLowerCase();
} else {
server = "global";
}
try {
group.unsetPermission("luckperms.group." + groupName, server);
Util.sendPluginMessage(sender, "&b" + group.getName() + "&a no longer inherits permissions from &b" + groupName + "&a on server &b" + server + "&a.");
saveGroup(group, sender, plugin);
} catch (ObjectLacksPermissionException e) {
Util.sendPluginMessage(sender, "That group does not inherit '" + groupName + "'.");
}
}
@Override
public boolean isArgLengthInvalid(int argLength) {
return argLength == 0;
}
}

View File

@ -0,0 +1,34 @@
package me.lucko.luckperms.commands.misc;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.MainCommand;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.commands.Util;
import java.util.ArrayList;
import java.util.List;
public class DebugCommand extends MainCommand {
public DebugCommand() {
super("Debug", "/perms debug", 0);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, List<String> args) {
if (!sender.hasPermission("luckperms.debug")) {
Util.sendPluginMessage(sender, "You do not have permission to use this command!");
return;
}
Util.sendPluginMessage(sender, "&d>> Debug Info");
Util.sendPluginMessage(sender, "&eOnline Players: &6" + plugin.getPlayerCount());
Util.sendPluginMessage(sender, "&eLoaded Users: &6" + plugin.getUserManager().getUsers().size());
Util.sendPluginMessage(sender, "&eLoaded Groups: &6" + plugin.getGroupManager().getGroups().size());
}
@Override
public List<? extends SubCommand> getSubCommands() {
return new ArrayList<>();
}
}

View File

@ -0,0 +1,33 @@
package me.lucko.luckperms.commands.misc;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.MainCommand;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.commands.Util;
import java.util.ArrayList;
import java.util.List;
public class InfoCommand extends MainCommand {
public InfoCommand() {
super("Info", "/perms info", 0);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, List<String> args) {
if (!sender.hasPermission("luckperms.info")) {
Util.sendPluginMessage(sender, "You do not have permission to use this command!");
return;
}
Util.sendPluginMessage(sender, "&6Running &bLuckPerms " + plugin.getVersion() + "&6.");
Util.sendPluginMessage(sender, "&eAuthor: &6Luck");
Util.sendPluginMessage(sender, "&eStorage Method: &6" + plugin.getDatastore().getName());
}
@Override
public List<? extends SubCommand> getSubCommands() {
return new ArrayList<>();
}
}

View File

@ -0,0 +1,32 @@
package me.lucko.luckperms.commands.misc;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.MainCommand;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.commands.Util;
import java.util.ArrayList;
import java.util.List;
public class SyncCommand extends MainCommand {
public SyncCommand() {
super("Sync", "/perms sync", 0);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, List<String> args) {
if (!sender.hasPermission("luckperms.sync")) {
Util.sendPluginMessage(sender, "You do not have permission to use this command!");
return;
}
Util.sendPluginMessage(sender, "&bRunning update task for all online users.");
plugin.runUpdateTask();
}
@Override
public List<? extends SubCommand> getSubCommands() {
return new ArrayList<>();
}
}

View File

@ -0,0 +1,115 @@
package me.lucko.luckperms.commands.user;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.MainCommand;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.users.User;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class UserMainCommand extends MainCommand{
private final List<UserSubCommand> subCommands = new ArrayList<>();
public UserMainCommand() {
super("User", "/perms user <user>", 2);
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, List<String> args) {
if (args.size() <= 1) {
sendUsage(sender);
return;
}
// The first argument is the name of the user, the second is the command
String command = args.get(1);
UserSubCommand tempSub = null;
// Try to identify the command used
for (UserSubCommand s : subCommands) {
if (s.getName().equalsIgnoreCase(command)) {
tempSub = s;
break;
}
}
// The command the sender used
final UserSubCommand sub = tempSub;
if (sub == null) {
Util.sendPluginMessage(sender, "Command not recognised.");
return;
}
if (!sub.isAuthorized(sender)) {
Util.sendPluginMessage(sender, "You do not have permission to use this command!");
return;
}
// The arguments to be passed onto the sub command
List<String> strippedArgs = new ArrayList<>();
if (args.size() > 2) {
strippedArgs.addAll(args.subList(2, args.size()));
}
String user = args.get(0);
UUID u = Util.parseUuid(user);
if (u != null) {
runSub(plugin, sender, u, sub, strippedArgs);
return;
}
if (user.length() <= 16) {
Util.sendPluginMessage(sender, "&7(Attempting UUID lookup, since you specified a user)");
plugin.getDatastore().getUUID(user, uuid -> {
if (uuid == null) {
Util.sendPluginMessage(sender, "&eUser could not be found.");
return;
}
runSub(plugin, sender, uuid, sub, strippedArgs);
});
return;
}
Util.sendPluginMessage(sender, "&d" + user + "&c is not a valid username/uuid.");
}
private void runSub(LuckPermsPlugin plugin, Sender sender, UUID uuid, UserSubCommand command, List<String> strippedArgs) {
plugin.getDatastore().loadUser(uuid, success -> {
if (!success) {
Util.sendPluginMessage(sender, "&eUser could not be found.");
return;
}
User user1 = plugin.getUserManager().getUser(uuid);
if (user1 == null) {
Util.sendPluginMessage(sender, "&eUser could not be found.");
}
if (command.isArgLengthInvalid(strippedArgs.size())) {
command.sendUsage(sender);
return;
}
command.execute(plugin, sender, user1, strippedArgs);
plugin.getUserManager().cleanupUser(user1);
});
}
@Override
public List<? extends SubCommand> getSubCommands() {
return subCommands;
}
public void registerSubCommand(UserSubCommand subCommand) {
subCommands.add(subCommand);
}
}

View File

@ -0,0 +1,29 @@
package me.lucko.luckperms.commands.user;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.users.User;
import java.util.List;
public abstract class UserSubCommand extends SubCommand {
public UserSubCommand(String name, String description, String usage, String permission) {
super(name, description, usage, permission);
}
protected abstract void execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args);
protected void saveUser(User user, Sender sender, LuckPermsPlugin plugin) {
user.refreshPermissions();
plugin.getDatastore().saveUser(user, success -> {
if (success) {
Util.sendPluginMessage(sender, "&7(User data was saved to the datastore)");
} else {
Util.sendPluginMessage(sender, "There was an error whilst saving the user.");
}
});
}
}

View File

@ -0,0 +1,49 @@
package me.lucko.luckperms.commands.user.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.user.UserSubCommand;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.users.User;
import java.util.List;
public class UserAddGroupCommand extends UserSubCommand {
public UserAddGroupCommand() {
super("addgroup", "Adds the user to a group",
"/perms user <user> addgroup <group> [server]", "luckperms.user.addgroup");
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args) {
String group = args.get(0).toLowerCase();
String server;
if (args.size() != 1) {
server = args.get(1);
} else {
server = "global";
}
Group group1 = plugin.getGroupManager().getGroup(group);
if (group1 == null) {
Util.sendPluginMessage(sender, "That group does not exist!");
return;
}
try {
user.addGroup(group1, server);
Util.sendPluginMessage(sender, "&b" + user.getName() + "&a successfully added to group &b" + group + "&a on the server &b" + server + "&a.");
} catch (ObjectAlreadyHasException e) {
Util.sendPluginMessage(sender, "The user is already a member of that group.");
}
saveUser(user, sender, plugin);
}
@Override
public boolean isArgLengthInvalid(int argLength) {
return (argLength != 1 && argLength != 2);
}
}

View File

@ -0,0 +1,30 @@
package me.lucko.luckperms.commands.user.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.user.UserSubCommand;
import me.lucko.luckperms.users.User;
import java.util.List;
public class UserClearCommand extends UserSubCommand {
public UserClearCommand() {
super("clear", "Clears a users permissions and groups",
"/perms user <user> clear", "luckperms.user.clear");
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args) {
user.clearNodes();
user.getNodes().put(plugin.getConfiguration().getDefaultGroupNode(), true);
Util.sendPluginMessage(sender, "&b" + user.getName() + "&a's permissions were cleared.");
saveUser(user, sender, plugin);
}
@Override
public boolean isArgLengthInvalid(int argLength) {
return false;
}
}

View File

@ -0,0 +1,25 @@
package me.lucko.luckperms.commands.user.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.user.UserSubCommand;
import me.lucko.luckperms.users.User;
import java.util.List;
public class UserGetUUIDCommand extends UserSubCommand {
public UserGetUUIDCommand() {
super("getuuid", "Get the UUID of a user", "/perms user <user> getuuid", "luckperms.user.getuuid");
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args) {
Util.sendPluginMessage(sender, "&bThe UUID of &e" + user.getName() + "&b is &e" + user.getUuid().toString() + "&b.");
}
@Override
public boolean isArgLengthInvalid(int argLength) {
return false;
}
}

View File

@ -0,0 +1,30 @@
package me.lucko.luckperms.commands.user.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.user.UserSubCommand;
import me.lucko.luckperms.users.User;
import java.util.List;
public class UserHasPermCommand extends UserSubCommand {
public UserHasPermCommand() {
super("haspermission", "Checks to see if a user has a certain permission node",
"/perms user <user> haspermission <node> [server]", "luckperms.user.haspermission");
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args) {
if (args.size() >= 2) {
Util.sendBoolean(sender, args.get(0), user.hasPermission(args.get(0), true, args.get(1)));
} else {
Util.sendBoolean(sender, args.get(0), user.hasPermission(args.get(0), true, "global"));
}
}
@Override
public boolean isArgLengthInvalid(int argLength) {
return argLength == 0;
}
}

View File

@ -0,0 +1,34 @@
package me.lucko.luckperms.commands.user.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.user.UserSubCommand;
import me.lucko.luckperms.users.User;
import java.util.List;
public class UserInfoCommand extends UserSubCommand {
public UserInfoCommand() {
super("info", "Gives info about the user",
"/perms user <user> info", "luckperms.user.info");
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args) {
final String prefix = plugin.getConfiguration().getPrefix();
String sb = prefix + "&d-> &eUser: &6" + user.getName() + "\n" +
prefix + "&d-> &eUUID: &6" + user.getUuid() + "\n" +
prefix + "&d-> &eStatus: " + plugin.getPlayerStatus(user.getUuid()) + "\n" +
prefix + "&d-> &eGroups: &6" + Util.listToCommaSep(user.getGroupNames()) + "\n" +
prefix + "&d-> &ePermissions: &6" + (user.getNodes().keySet().size() - user.getGroupNames().size()) + "\n" +
prefix + "&d-> &bUse &a/perms user " + user.getName() + " listnodes &bto see all permissions.";
sender.sendMessage(Util.color(sb));
}
@Override
public boolean isArgLengthInvalid(int argLength) {
return false;
}
}

View File

@ -0,0 +1,27 @@
package me.lucko.luckperms.commands.user.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.user.UserSubCommand;
import me.lucko.luckperms.users.User;
import java.util.List;
public class UserListNodesCommand extends UserSubCommand {
public UserListNodesCommand() {
super("listnodes", "Lists the permission nodes the user has",
"/perms user <user> listnodes", "luckperms.user.listnodes");
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args) {
Util.sendPluginMessage(sender, "&e" + user.getName() + "'s Nodes:");
sender.sendMessage(Util.color(Util.nodesToString(user.getNodes())));
}
@Override
public boolean isArgLengthInvalid(int argLength) {
return false;
}
}

View File

@ -0,0 +1,49 @@
package me.lucko.luckperms.commands.user.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.user.UserSubCommand;
import me.lucko.luckperms.exceptions.ObjectLacksPermissionException;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.users.User;
import java.util.List;
public class UserRemoveGroupCommand extends UserSubCommand {
public UserRemoveGroupCommand() {
super("removegroup", "Removes a user from a group",
"/perms user <user> removegroup <group> [server]", "luckperms.user.removegroup");
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args) {
String group = args.get(0).toLowerCase();
String server;
if (args.size() != 1) {
server = args.get(1);
} else {
server = "global";
}
Group group1 = plugin.getGroupManager().getGroup(group);
if (group1 == null) {
Util.sendPluginMessage(sender, "That group does not exist!");
return;
}
try {
user.removeGroup(group1, server);
Util.sendPluginMessage(sender, "&b" + user.getName() + "&a was removed from group &b" + group + "&a on server &b" + server + "&a.");
} catch (ObjectLacksPermissionException e) {
Util.sendPluginMessage(sender, "The user is not a member of that group.");
}
saveUser(user, sender, plugin);
}
@Override
public boolean isArgLengthInvalid(int argLength) {
return (argLength != 1 && argLength != 2);
}
}

View File

@ -0,0 +1,60 @@
package me.lucko.luckperms.commands.user.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.user.UserSubCommand;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.users.User;
import java.util.List;
public class UserSetPermissionCommand extends UserSubCommand {
public UserSetPermissionCommand() {
super("set", "Sets a permission for a user",
"/perms user <user> set <node> <true|false> [server]", "luckperms.user.setpermission");
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args) {
String node = args.get(0);
String bool = args.get(1);
if (node.contains("/")) {
sendUsage(sender);
return;
}
if (node.matches(".*luckperms\\.group\\..*")) {
Util.sendPluginMessage(sender, "Use the addgroup command instead of specifying the node.");
return;
}
if (!bool.equalsIgnoreCase("true") && !bool.equalsIgnoreCase("false")) {
sendUsage(sender);
return;
}
boolean b = Boolean.parseBoolean(bool);
try {
if (args.size() == 3) {
final String server = args.get(2).toLowerCase();
user.setPermission(node, b, server);
Util.sendPluginMessage(sender, "&aSet &b" + node + "&a to " + bool + " for &b" + user.getName() + "&a on server &b" + server + "&a.");
} else {
user.setPermission(node, b);
Util.sendPluginMessage(sender, "&aSet &b" + node + "&a to " + bool + " for &b" + user.getName() + "&a.");
}
} catch (ObjectAlreadyHasException e) {
Util.sendPluginMessage(sender, "That user already has this permission!");
}
saveUser(user, sender, plugin);
}
@Override
public boolean isArgLengthInvalid(int argLength) {
return argLength < 2;
}
}

View File

@ -0,0 +1,51 @@
package me.lucko.luckperms.commands.user.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.commands.user.UserSubCommand;
import me.lucko.luckperms.exceptions.ObjectLacksPermissionException;
import me.lucko.luckperms.users.User;
import java.util.List;
public class UserUnSetPermissionCommand extends UserSubCommand {
public UserUnSetPermissionCommand() {
super("unset", "Unsets a permission for a user",
"/perms user <user> unset <node> [server]", "luckperms.user.unsetpermission");
}
@Override
protected void execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args) {
String node = args.get(0);
if (node.contains("/")) {
sendUsage(sender);
return;
}
if (node.matches(".*luckperms\\.group\\..*")) {
Util.sendPluginMessage(sender, "Use the removegroup command instead of specifying the node.");
return;
}
try {
if (args.size() == 2) {
final String server = args.get(1).toLowerCase();
user.unsetPermission(node, server);
Util.sendPluginMessage(sender, "&aUnset &b" + node + "&a for &b" + user.getName() + "&a on server &b" + server + "&a.");
} else {
user.unsetPermission(node);
Util.sendPluginMessage(sender, "&aUnset &b" + node + "&a for &b" + user.getName() + "&a.");
}
} catch (ObjectLacksPermissionException e) {
Util.sendPluginMessage(sender, "That user does not have this permission set.");
}
saveUser(user, sender, plugin);
}
@Override
public boolean isArgLengthInvalid(int argLength) {
return argLength == 0;
}
}

View File

@ -0,0 +1,117 @@
package me.lucko.luckperms.data;
import lombok.Getter;
import lombok.Setter;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.users.User;
import java.util.UUID;
public abstract class Datastore {
protected final LuckPermsPlugin plugin;
@Getter
public String name;
@Getter
@Setter
private boolean acceptingLogins;
public Datastore(LuckPermsPlugin plugin, String name) {
this.plugin = plugin;
this.name = name;
this.acceptingLogins = true;
}
/**
* Execute a runnable asynchronously
* @param r the task to run
*/
private void doAsync(Runnable r) {
plugin.doAsync(r);
}
/**
* Execute a runnable synchronously
* @param r the task to run
*/
private void doSync(Runnable r) {
plugin.doSync(r);
}
private void runCallback(boolean result, Callback callback) {
doSync(() -> callback.onComplete(result));
}
/*
These methods will block the thread that they're ran on.
*/
public abstract void init(DatastoreConfiguration configuration);
public abstract boolean loadOrCreateUser(UUID uuid, String username);
public abstract boolean loadUser(UUID uuid);
public abstract boolean saveUser(User user);
public abstract boolean createAndLoadGroup(String name);
public abstract boolean loadGroup(String name);
public abstract boolean loadAllGroups();
public abstract boolean saveGroup(Group group);
public abstract boolean deleteGroup(Group group);
public abstract boolean saveUUIDData(String username, UUID uuid);
public abstract UUID getUUID(String username);
/*
These methods will return as soon as they are called. The callback will be ran when the task is complete
They therefore will not block the thread that they're ran on
Callbacks are ran on the main server thread (if applicable)
*/
public void loadOrCreateUser(UUID uuid, String username, Callback callback) {
doAsync(() -> runCallback(loadOrCreateUser(uuid, username), callback));
}
public void loadUser(UUID uuid, Callback callback) {
doAsync(() -> runCallback(loadUser(uuid), callback));
}
public void saveUser(User user, Callback callback) {
doAsync(() -> runCallback(saveUser(user), callback));
}
public void createAndLoadGroup(String name, Callback callback) {
doAsync(() -> runCallback(createAndLoadGroup(name), callback));
}
public void loadGroup(String name, Callback callback) {
doAsync(() -> runCallback(loadGroup(name), callback));
}
public void loadAllGroups(Callback callback) {
doAsync(() -> runCallback(loadAllGroups(), callback));
}
public void saveGroup(Group group, Callback callback) {
doAsync(() -> runCallback(saveGroup(group), callback));
}
public void deleteGroup(Group group, Callback callback) {
doAsync(() -> runCallback(deleteGroup(group), callback));
}
public void saveUUIDData(String username, UUID uuid, Callback callback) {
doAsync(() -> runCallback(saveUUIDData(username, uuid), callback));
}
public void getUUID(String username, GetUUIDCallback callback) {
doAsync(() -> doSync(() -> callback.onComplete(getUUID(username))));
}
public interface Callback {
void onComplete(boolean success);
}
public interface GetUUIDCallback {
void onComplete(UUID uuid);
}
}

View File

@ -0,0 +1,15 @@
package me.lucko.luckperms.data;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public class DatastoreConfiguration {
private final String address;
private final String database;
private final String username;
private final String password;
}

View File

@ -0,0 +1,338 @@
package me.lucko.luckperms.data;
import com.zaxxer.hikari.HikariDataSource;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.groups.GroupManager;
import me.lucko.luckperms.users.User;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.logging.Level;
public class HikariDatastore extends Datastore {
private static final String CREATETABLE_UUID = "CREATE TABLE IF NOT EXISTS `lp_uuid` (`name` VARCHAR(16) NOT NULL, `uuid` VARCHAR(36) NOT NULL, PRIMARY KEY (`name`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;";
private static final String CREATETABLE_USERS = "CREATE TABLE IF NOT EXISTS `lp_users` (`uuid` VARCHAR(36) NOT NULL, `name` VARCHAR(16) NOT NULL, `perms` TEXT NOT NULL, PRIMARY KEY (`uuid`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;";
private static final String CREATETABLE_GROUPS = "CREATE TABLE IF NOT EXISTS `lp_groups` (`name` VARCHAR(36) NOT NULL, `perms` TEXT NULL, PRIMARY KEY (`name`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;";
private static final String USER_INSERT = "INSERT INTO lp_users VALUES(?, ?, ?) ON DUPLICATE KEY UPDATE name=?";
private static final String USER_SELECT = "SELECT * FROM lp_users WHERE uuid=?";
private static final String USER_SAVE = "UPDATE lp_users SET name=?, perms=? WHERE uuid=?";
private static final String GROUP_INSERT = "INSERT INTO lp_groups VALUES(?, ?) ON DUPLICATE KEY UPDATE perms=?";
private static final String GROUP_SELECT = "SELECT perms FROM lp_groups WHERE name=?";
private static final String GROUP_SELECT_ALL = "SELECT * FROM lp_groups";
private static final String GROUP_SAVE = "UPDATE lp_groups SET perms=? WHERE name=?";
private static final String GROUP_DELETE = "DELETE FROM lp_groups WHERE name=?";
private static final String UUIDCACHE_INSERT = "INSERT INTO lp_uuid VALUES(?, ?) ON DUPLICATE KEY UPDATE uuid=?";
private static final String UUIDCACHE_SELECT = "SELECT uuid FROM lp_uuid WHERE name=?";
private HikariDataSource hikari;
public HikariDatastore(LuckPermsPlugin plugin) {
super(plugin, "MySQL");
}
private static void executeQuery(Connection connection, String query) throws SQLException {
PreparedStatement preparedStatement = connection.prepareStatement(query);
preparedStatement.execute();
preparedStatement.close();
}
private boolean runQuery(Query query) {
boolean success = false;
Connection connection = null;
try {
connection = hikari.getConnection();
success = query.onRun(connection);
} catch (SQLException e) {
e.printStackTrace();
success = false;
} finally {
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return success;
}
private void setupTables() {
boolean success = runQuery(connection -> {
executeQuery(connection, CREATETABLE_UUID);
executeQuery(connection, CREATETABLE_USERS);
executeQuery(connection, CREATETABLE_GROUPS);
return true;
});
if (!success) {
plugin.getLogger().log(Level.SEVERE, "Error occurred whilst connecting to the database. All connections are disallowed.");
hikari.shutdown();
setAcceptingLogins(false);
}
}
@Override
public void init(DatastoreConfiguration configuration) {
hikari = new HikariDataSource();
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);
setupTables();
}
@Override
public boolean loadUser(UUID uuid) {
User user = plugin.getUserManager().makeUser(uuid);
boolean success = runQuery(connection -> {
PreparedStatement preparedStatement = connection.prepareStatement(USER_SELECT);
preparedStatement.setString(1, uuid.toString());
ResultSet resultSet = preparedStatement.executeQuery();
List<String> nodes = new ArrayList<>();
if (resultSet.next()) {
if (!resultSet.getString("perms").equals("#")) {
nodes.addAll(Arrays.asList(resultSet.getString("perms").split(":")));
}
user.setName(resultSet.getString("name"));
user.loadNodes(nodes);
preparedStatement.close();
resultSet.close();
return true;
}
preparedStatement.close();
resultSet.close();
return false;
});
if (success) plugin.getUserManager().updateOrSetUser(user);
return success;
}
@Override
public boolean loadOrCreateUser(UUID uuid, String username) {
User user = plugin.getUserManager().makeUser(uuid, username);
boolean success = runQuery(connection -> {
PreparedStatement preparedStatement = connection.prepareStatement(USER_INSERT);
preparedStatement.setString(1, uuid.toString());
preparedStatement.setString(2, username);
preparedStatement.setString(3, plugin.getConfiguration().getDefaultGroupNode());
preparedStatement.setString(4, username);
preparedStatement.execute();
preparedStatement.close();
preparedStatement = connection.prepareStatement(USER_SELECT);
preparedStatement.setString(1, uuid.toString());
ResultSet resultSet = preparedStatement.executeQuery();
List<String> nodes = new ArrayList<>();
if (resultSet.next()) {
if (!resultSet.getString("perms").equals("#")) {
nodes.addAll(Arrays.asList(resultSet.getString("perms").split(":")));
}
user.loadNodes(nodes);
preparedStatement.close();
resultSet.close();
return true;
}
preparedStatement.close();
resultSet.close();
return true;
});
if (success) plugin.getUserManager().updateOrSetUser(user);
return success;
}
@Override
public boolean saveUser(User user) {
boolean success = runQuery(connection -> {
PreparedStatement preparedStatement = connection.prepareStatement(USER_SAVE);
preparedStatement.setString(1, user.getName());
preparedStatement.setString(2, user.serializeNodes());
preparedStatement.setString(3, user.getUuid().toString());
preparedStatement.execute();
preparedStatement.close();
return true;
});
return success;
}
@Override
public boolean createAndLoadGroup(String name) {
Group group = plugin.getGroupManager().makeGroup(name);
boolean success = runQuery(connection -> {
PreparedStatement preparedStatement = connection.prepareStatement(GROUP_INSERT);
preparedStatement.setString(1, name);
preparedStatement.setString(2, "#");
preparedStatement.setString(3, "#");
preparedStatement.execute();
preparedStatement.close();
preparedStatement = connection.prepareStatement(GROUP_SELECT);
preparedStatement.setString(1, name);
ResultSet resultSet = preparedStatement.executeQuery();
List<String> nodes = new ArrayList<>();
if (resultSet.next()) {
if (!resultSet.getString("perms").equals("#")) {
nodes.addAll(Arrays.asList(resultSet.getString("perms").split(":")));
}
}
group.loadNodes(nodes);
preparedStatement.close();
resultSet.close();
return true;
});
if (success) plugin.getGroupManager().updateOrSetGroup(group);
return success;
}
@Override
public boolean loadGroup(String name) {
Group group = plugin.getGroupManager().makeGroup(name);
boolean success = runQuery(connection -> {
PreparedStatement preparedStatement = connection.prepareStatement(GROUP_SELECT);
preparedStatement.setString(1, name);
ResultSet resultSet = preparedStatement.executeQuery();
List<String> nodes = new ArrayList<>();
if (resultSet.next()) {
if (!resultSet.getString("perms").equals("#")) {
nodes.addAll(Arrays.asList(resultSet.getString("perms").split(":")));
}
group.loadNodes(nodes);
return true;
}
preparedStatement.close();
resultSet.close();
return false;
});
if (success) plugin.getGroupManager().updateOrSetGroup(group);
return success;
}
@Override
public boolean loadAllGroups() {
List<Group> groups = new ArrayList<>();
boolean success = runQuery(connection -> {
PreparedStatement preparedStatement = connection.prepareStatement(GROUP_SELECT_ALL);
ResultSet resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
Group group = plugin.getGroupManager().makeGroup(resultSet.getString("name"));
if (!resultSet.getString("perms").equals("#")) {
group.loadNodes(Arrays.asList(resultSet.getString("perms").split(":")));
}
groups.add(group);
}
preparedStatement.close();
resultSet.close();
return true;
});
GroupManager gm = plugin.getGroupManager();
if (success) {
groups.forEach(gm::setGroup);
}
return success;
}
@Override
public boolean saveGroup(Group group) {
boolean success = runQuery(connection -> {
PreparedStatement preparedStatement = connection.prepareStatement(GROUP_SAVE);
preparedStatement.setString(1, group.serializeNodes());
preparedStatement.setString(2, group.getName());
preparedStatement.execute();
preparedStatement.close();
return true;
});
return success;
}
@Override
public boolean deleteGroup(Group group) {
boolean success = runQuery(connection -> {
PreparedStatement preparedStatement = connection.prepareStatement(GROUP_DELETE);
preparedStatement.setString(1, group.getName());
preparedStatement.execute();
preparedStatement.close();
return true;
});
if (success) plugin.getGroupManager().unloadGroup(group);
return success;
}
@Override
public boolean saveUUIDData(String username, UUID uuid) {
boolean success = runQuery(connection -> {
PreparedStatement preparedStatement = connection.prepareStatement(UUIDCACHE_INSERT);
preparedStatement.setString(1, username);
preparedStatement.setString(2, uuid.toString());
preparedStatement.setString(3, uuid.toString());
preparedStatement.execute();
preparedStatement.close();
return true;
});
return success;
}
@Override
public UUID getUUID(String username) {
final UUID[] uuid = {null};
boolean success = runQuery(connection -> {
PreparedStatement preparedStatement = connection.prepareStatement(UUIDCACHE_SELECT);
preparedStatement.setString(1, username);
ResultSet resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {
uuid[0] = UUID.fromString(resultSet.getString("uuid"));
preparedStatement.close();
resultSet.close();
return true;
}
preparedStatement.close();
resultSet.close();
return false;
});
return success ? uuid[0] : null;
}
private interface Query {
boolean onRun(Connection connection) throws SQLException;
}
}

View File

@ -0,0 +1,4 @@
package me.lucko.luckperms.exceptions;
public class ObjectAlreadyHasException extends Exception {
}

View File

@ -0,0 +1,4 @@
package me.lucko.luckperms.exceptions;
public class ObjectLacksPermissionException extends Exception {
}

View File

@ -0,0 +1,31 @@
package me.lucko.luckperms.groups;
import lombok.Getter;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.utils.PermissionObject;
public class Group extends PermissionObject {
/**
* The name of the group
*/
@Getter
private final String name;
public Group(String name, LuckPermsPlugin plugin) {
super(plugin, name);
this.name = name;
}
/**
* Clear all of the groups permission nodes
*/
public void clearNodes() {
getNodes().clear();
}
@Override
public String toString() {
return getName();
}
}

View File

@ -0,0 +1,93 @@
package me.lucko.luckperms.groups;
import lombok.Getter;
import me.lucko.luckperms.LuckPermsPlugin;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class GroupManager {
private final LuckPermsPlugin plugin;
/**
* A {@link Map} containing all loaded groups
*/
@Getter
private final Map<String, Group> groups = new ConcurrentHashMap<>();
public GroupManager(LuckPermsPlugin plugin) {
this.plugin = plugin;
loadAllGroups();
}
/**
* Get a group object by name
* @param name The name to search by
* @return a {@link Group} object if the group is loaded, returns null if the group is not loaded
*/
public Group getGroup(String name) {
return groups.get(name);
}
/**
* Add a group to the loaded groups map
* @param group The group to add
*/
public void setGroup(Group group) {
groups.put(group.getName(), group);
}
/**
* Updates (or sets if the group wasn't already loaded) a group in the groups map
* @param group The group to update or set
*/
public void updateOrSetGroup(Group group) {
if (!groups.containsKey(group.getName())) {
// The group isn't already loaded
groups.put(group.getName(), group);
} else {
groups.get(group.getName()).setNodes(group.getNodes());
}
}
/**
* Check to see if a group is loaded or not
* @param name The name of the group
* @return true if the group is loaded
*/
public boolean isLoaded(String name) {
return groups.containsKey(name);
}
/**
* Removes and unloads the group from the plugins internal storage
* @param group The group to unload
*/
public void unloadGroup(Group group) {
if (group != null) {
groups.remove(group.getName());
}
}
/**
* Load all groups from the datastore
*/
public void loadAllGroups() {
plugin.getDatastore().loadAllGroups(success -> {
String defaultGroup = plugin.getConfiguration().getDefaultGroupName();
if (!groups.keySet().contains(defaultGroup)) {
plugin.getDatastore().createAndLoadGroup(defaultGroup, success1 -> {});
}
});
}
/**
* Makes a new group object
* @param name The name of the group
* @return a new {@link Group} object
*/
public Group makeGroup(String name) {
return new Group(name, plugin);
}
}

View File

@ -0,0 +1,197 @@
package me.lucko.luckperms.users;
import lombok.Getter;
import lombok.Setter;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksPermissionException;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.utils.PermissionObject;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public abstract class User extends PermissionObject {
/**
* The users Mojang UUID
*/
@Getter
private final UUID uuid;
/**
* The last known username of a player
*/
@Getter
@Setter
private String name;
public User(UUID uuid, LuckPermsPlugin plugin) {
super(plugin, uuid.toString());
this.uuid = uuid;
this.name = null;
}
public User(UUID uuid, String name, LuckPermsPlugin plugin) {
super(plugin, uuid.toString());
this.uuid = uuid;
this.name = name;
}
/**
* Refresh and re-assign the users permissions
*/
public abstract void refreshPermissions();
/**
* Check to see if the user is a member of a group
* @param group The group to check membership of
* @return true if the user is a member of the group
*/
public boolean isInGroup(Group group) {
return isInGroup(group, "global");
}
/**
* Check to see if a user is a member of a group on a specific server
* @param group The group to check membership of
* @param server The server to check on
* @return true if the user is a member of the group
*/
public boolean isInGroup(Group group, String server) {
return getLocalGroups(server).contains(group.getName());
}
/**
* Add a user to a group
* @param group The group to add the user to
* @throws ObjectAlreadyHasException if the user is already a member of the group
*/
public void addGroup(Group group) throws ObjectAlreadyHasException {
addGroup(group, "global");
}
/**
* Add a user to a group on a specific server
* @param group The group to add the user to
* @param server The server to add the group on
* @throws ObjectAlreadyHasException if the user is already a member of the group on that server
*/
public void addGroup(Group group, String server) throws ObjectAlreadyHasException {
if (server == null) {
server = "global";
}
if (isInGroup(group, server)) {
throw new ObjectAlreadyHasException();
}
if (server.equalsIgnoreCase("global")) {
getNodes().put("luckperms.group." + group.getName(), true);
} else {
getNodes().put(server + "/luckperms.group." + group.getName(), true);
}
}
/**
* Remove the user from a group
* @param group the group to remove the user from
* @throws ObjectLacksPermissionException
*/
public void removeGroup(Group group) throws ObjectLacksPermissionException {
removeGroup(group, "global");
}
/**
* Remove the user from a group
* @param group The group to remove the user from
* @param server The server to remove the group on
* @throws ObjectLacksPermissionException if the user isn't a member of the group
*/
public void removeGroup(Group group, String server) throws ObjectLacksPermissionException {
if (server == null) {
server = "global";
}
if (!getLocalGroups(server).contains(group.getName())) {
throw new ObjectLacksPermissionException();
}
if (server.equalsIgnoreCase("global")) {
getNodes().remove("luckperms.group." + group.getName());
} else {
getNodes().remove(server + "/luckperms.group." + group.getName());
}
}
/**
* Clear all of the users permission nodes
*/
public void clearNodes() {
String defaultGroupNode = getPlugin().getConfiguration().getDefaultGroupNode();
getNodes().clear();
getNodes().put(defaultGroupNode, true);
}
/**
* Get a {@link List} of all of the groups the user is a member of, on all servers
* @return a {@link List} of group names
*/
public List<String> getGroupNames() {
return getGroups(null, true, true);
}
/**
* Get a {@link List} of the groups the user is a member of on a specific server
* @param server the server to check
* @return a {@link List} of group names
*/
public List<String> getLocalGroups(String server) {
return getGroups(server, false, false);
}
/**
* Get a {@link List} of the groups the user is a member of on a specific server with the option to include global groups or all groups
* @param server Which server to check on
* @param includeGlobal Whether to include global groups
* @param includeAll Whether to get all groups
* @return a {@link List} of group names
*/
public List<String> getGroups(String server, boolean includeGlobal, boolean includeAll) {
List<String> groups = new ArrayList<>();
if (server == null || server.equals("")) {
server = "global";
}
for (String node : getNodes().keySet()) {
String originalNode = node;
// Has a defined server
if (node.contains("/")) {
String[] parts = node.split("\\/", 2);
if (!parts[0].equalsIgnoreCase(server) && !includeAll) {
continue;
}
node = parts[1];
} else {
if (!includeGlobal) {
continue;
}
}
if (node.matches("luckperms\\.group\\..*")) {
if (getNodes().get(originalNode)) {
String groupName = node.split("\\.", 3)[2];
groups.add(groupName);
}
}
}
return groups;
}
@Override
public String toString() {
return getUuid().toString();
}
}

View File

@ -0,0 +1,120 @@
package me.lucko.luckperms.users;
import lombok.Getter;
import lombok.NoArgsConstructor;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import me.lucko.luckperms.data.Datastore;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
@NoArgsConstructor
public abstract class UserManager {
/**
* A {@link Map} containing all online/loaded users
*/
@Getter
private final Map<UUID, User> users = new ConcurrentHashMap<>();
/**
* Get a user object by UUID
* @param uuid The uuid to search by
* @return a {@link User} object if the user is loaded, returns null if the user is not loaded
*/
public User getUser(UUID uuid) {
return users.get(uuid);
}
/**
* Get a user object by name
* @param name The name to search by
* @return a {@link User} object if the user is loaded, returns null if the user is not loaded
*/
public User getUser(String name) {
User user = null;
for (User u : users.values()) {
if (u.getName().equalsIgnoreCase(name)) {
user = u;
break;
}
}
return user;
}
/**
* Add a user to the {@link #getUsers()} map
* @param user the user to add
*/
public void setUser(User user) {
users.put(user.getUuid(), user);
}
/**
* Updates (or sets if the user wasn't already loaded) a user in the {@link #getUsers()} map
* @param user The user to update or set
*/
public void updateOrSetUser(User user) {
if (!users.containsKey(user.getUuid())) {
// The user isn't already loaded, so we can just add
users.put(user.getUuid(), user);
// They're probably not online, but in case they are...
user.refreshPermissions();
} else {
// Override the user's current loaded nodes, and force a refresh
users.get(user.getUuid()).setNodes(user.getNodes());
users.get(user.getUuid()).refreshPermissions();
}
}
/**
* Saves a user object in the datastore
* @param user the user to save
* @param datastore the datastore
*/
public void saveUser(User user, Datastore datastore) {
user.refreshPermissions();
datastore.saveUser(user, success -> {});
}
/**
* Check to see if a user is loaded or not
* @param uuid the UUID of the user
* @return true if the user is loaded
*/
public boolean isLoaded(UUID uuid) {
return users.containsKey(uuid);
}
/**
* Removes and unloads any permission links of the user from the internal storage
* @param user The user to unload
*/
public abstract void unloadUser(User user);
/**
* Checks to see if the user is online, and if they are not, runs {@link #unloadUser(User)}
* @param user The user to be cleaned up
*/
public abstract void cleanupUser(User user);
/**
* Makes a new {@link User} object
* @param uuid The UUID of the user
* @return a new {@link User} object
*/
public abstract User makeUser(UUID uuid);
/**
* Makes a new {@link User} object
* @param uuid The UUID of the user
* @param username The username of the user
* @return a new {@link User} object
*/
public abstract User makeUser(UUID uuid, String username);
}

View File

@ -0,0 +1,13 @@
package me.lucko.luckperms.utils;
public interface LPConfiguration {
String getServer();
String getPrefix();
int getSyncTime();
String getDefaultGroupNode();
String getDefaultGroupName();
boolean getIncludeGlobalPerms();
String getDatabaseValue(String value);
}

View File

@ -0,0 +1,234 @@
package me.lucko.luckperms.utils;
import lombok.Getter;
import lombok.Setter;
import lombok.NonNull;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksPermissionException;
import me.lucko.luckperms.groups.Group;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* Represents an object that can hold permissions
* For example a User or a Group
*/
@Getter
public abstract class PermissionObject {
/**
* The UUID of the user / name of the group.
* Used to prevent circular inheritance issues
*/
private final String objectName;
/**
* Reference to the main plugin instance
*/
private final LuckPermsPlugin plugin;
/**
* If false, only permissions specific to the server are applied
*/
@Setter
private boolean includeGlobalPermissions;
/**
* The user/group's permissions
*/
@Setter
private Map<String, Boolean> nodes = new HashMap<>();
public PermissionObject(LuckPermsPlugin plugin, String objectName) {
this.objectName = objectName;
this.plugin = plugin;
this.includeGlobalPermissions = plugin.getConfiguration().getIncludeGlobalPerms();
}
/**
* Checks to see if the object has a certain permission
* @param node The permission node
* @param b If the node is true/false(negated)
* @return true if the user has the permission
*/
public boolean hasPermission(String node, Boolean b) {
if (node.startsWith("global/")) node = node.replace("global/", "");
if (b) {
return getNodes().containsKey(node) && getNodes().get(node);
}
return getNodes().containsKey(node) && !getNodes().get(node);
}
/**
* Checks to see the the object has a permission on a certain server
* @param node The permission node
* @param b If the node is true/false(negated)
* @param server The server
* @return true if the user has the permission
*/
public boolean hasPermission(String node, Boolean b, String server) {
return hasPermission(server + "/" + node, b);
}
/**
* Sets a permission for the object
* @param node The node to be set
* @param value What to set the node to - true/false(negated)
* @throws ObjectAlreadyHasException if the object already has the permission
*/
public void setPermission(String node, Boolean value) throws ObjectAlreadyHasException {
if (node.startsWith("global/")) node = node.replace("global/", "");
if (hasPermission(node, value)) {
throw new ObjectAlreadyHasException();
}
getNodes().put(node, value);
}
/**
* Sets a permission for the object
* @param node The node to set
* @param value What to set the node to - true/false(negated)
* @param server The server to set the permission on
* @throws ObjectAlreadyHasException if the object already has the permission
*/
public void setPermission(String node, Boolean value, String server) throws ObjectAlreadyHasException {
setPermission(server + "/" + node, value);
}
/**
* Unsets a permission for the object
* @param node The node to be unset
* @throws ObjectLacksPermissionException if the node wasn't already set
*/
public void unsetPermission(String node) throws ObjectLacksPermissionException {
if (node.startsWith("global/")) node = node.replace("global/", "");
if (!getNodes().containsKey(node)) {
throw new ObjectLacksPermissionException();
}
getNodes().remove(node);
}
/**
* Unsets a permission for the object
* @param node The node to be unset
* @param server The server to unset the node on
* @throws ObjectLacksPermissionException if the node wasn't already set
*/
public void unsetPermission(String node, String server) throws ObjectLacksPermissionException {
unsetPermission(server + "/" + node);
}
/**
* Gets the permissions and inherited permissions that apply to a specific server
* @param server The server to get nodes for
* @param excludedGroups Groups that shouldn't be inherited (to prevent circular inheritance issues)
* @return a {@link Map} of the permissions
*/
public Map<String, Boolean> getLocalPermissions(String server, List<String> excludedGroups) {
return getPermissions(server, excludedGroups, includeGlobalPermissions);
}
private Map<String, Boolean> getPermissions(String server, List<String> excludedGroups, boolean includeGlobal) {
if (excludedGroups == null) {
excludedGroups = new ArrayList<>();
}
excludedGroups.add(getObjectName());
Map<String, Boolean> perms = new HashMap<>();
if (server == null || server.equals("")) {
server = "global";
}
for (String node : getNodes().keySet()) {
String originalNode = node;
// Has a defined server
if (node.contains("/")) {
String[] parts = node.split("\\/", 2);
if (!parts[0].equalsIgnoreCase(server)) {
continue;
}
node = parts[1];
perms.put(node, getNodes().get(originalNode));
continue;
}
if (node.matches("luckperms\\.group\\..*")) {
if (getNodes().get(originalNode)) {
String groupName = node.split("\\.", 3)[2];
Group group = plugin.getGroupManager().getGroup(groupName);
if (!excludedGroups.contains(groupName)) {
if (group != null) {
perms.putAll(group.getLocalPermissions(server, excludedGroups));
} else {
plugin.getLogger().warning("Error whilst refreshing the permissions of '" + objectName + "'." +
"\n The group '" + groupName + "' is not loaded.");
}
}
}
perms.put(node, getNodes().get(originalNode));
continue;
}
if (includeGlobal) perms.put(node, getNodes().get(originalNode));
}
return perms;
}
/**
* Loads a list of semi-serialised nodes into the object
* @param data The data to be loaded
*/
public void loadNodes(List<String> data) {
// String is the node in format "server/plugin.command-false" or "plugin.command-false" or "server/plugin.command"
// or just "plugin.command"
for (String s : data) {
String[] parts = s.split("-", 2);
if (parts.length == 2) {
nodes.put(parts[0], Boolean.valueOf(parts[1]));
} else {
nodes.put(parts[0], true);
}
}
}
/**
* Convert the permission nodes map to a list of strings
* @return a {@link List} of nodes
*/
public List<String> getNodesAsString() {
List<String> data = new ArrayList<>();
for (String node : nodes.keySet()) {
if (nodes.get(node)) {
data.add(node);
} else {
data.add(node + "-false");
}
}
return data;
}
/**
* Serialize the nodes in the object to be saved in the datastore
* @return A serialized string
*/
public String serializeNodes() {
if (nodes.isEmpty()) return "#";
return getNodesAsString().stream().collect(Collectors.joining(":"));
}
}

62
pom.xml Normal file
View File

@ -0,0 +1,62 @@
<?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">
<modelVersion>4.0.0</modelVersion>
<groupId>me.lucko</groupId>
<artifactId>luckperms</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<module>bukkit</module>
<module>common</module>
<module>bungee</module>
</modules>
<packaging>pom</packaging>
<repositories>
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
<repository>
<id>oss-sonatype-snapshots</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
</repository>
<repository>
<id>vault-repo</id>
<url>http://nexus.theyeticave.net/content/repositories/pub_releases</url>
</repository>
</repositories>
<dependencies>
<!-- HikariCP -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP-java6</artifactId>
<version>2.0.1</version>
<scope>compile</scope>
</dependency>
<!-- Javaassist library -->
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.18.1-GA</version>
</dependency>
<!-- slf4j library -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.5</version>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.8</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>