Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions bukkit/src/main/resources/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,16 @@ redis:
address: localhost
username: ''
password: ''
# Settings for Redis Sentinel.
# Sentinel provides high availability for Redis by monitoring master/replica instances.
# Port 26379 is used by default for sentinel nodes.
sentinel:
enabled: false
master: mymaster
addresses:
- localhost:26379
username: ''
password: ''

# Settings for Nats.
# Port 4222 is used by default; set address to "host:port" if differs
Expand Down
4 changes: 3 additions & 1 deletion bukkit/src/main/resources/luckperms.commodore
Original file line number Diff line number Diff line change
Expand Up @@ -543,7 +543,9 @@ luckperms {

editor;
listmembers {
page brigadier:integer;
page brigadier:integer {
context brigadier:string greedy_phrase;
}
}
setweight {
weight brigadier:integer;
Expand Down
10 changes: 10 additions & 0 deletions bungee/src/main/resources/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,16 @@ redis:
address: localhost
username: ''
password: ''
# Settings for Redis Sentinel.
# Sentinel provides high availability for Redis by monitoring master/replica instances.
# Port 26379 is used by default for sentinel nodes.
sentinel:
enabled: false
master: mymaster
addresses:
- localhost:26379
username: ''
password: ''

# Settings for Nats.
# Port 4222 is used by default; set address to "host:port" if differs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,8 @@ public enum CommandSpec {

GROUP_INFO,
GROUP_LISTMEMBERS(
arg("page", false)
arg("page", false),
arg("context...", false)
),
GROUP_SETWEIGHT(
arg("weight", true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,12 @@
import com.google.common.collect.Maps;
import me.lucko.luckperms.common.cache.LoadingMap;
import me.lucko.luckperms.common.command.abstraction.ChildCommand;
import me.lucko.luckperms.common.command.abstraction.CommandException;
import me.lucko.luckperms.common.command.access.ArgumentPermissions;
import me.lucko.luckperms.common.command.access.CommandPermission;
import me.lucko.luckperms.common.command.spec.CommandSpec;
import me.lucko.luckperms.common.command.tabcomplete.TabCompleter;
import me.lucko.luckperms.common.command.tabcomplete.TabCompletions;
import me.lucko.luckperms.common.command.utils.ArgumentList;
import me.lucko.luckperms.common.locale.Message;
import me.lucko.luckperms.common.model.Group;
Expand All @@ -46,6 +49,7 @@
import me.lucko.luckperms.common.storage.misc.NodeEntry;
import me.lucko.luckperms.common.util.Iterators;
import me.lucko.luckperms.common.util.Predicates;
import net.luckperms.api.context.ImmutableContextSet;
import net.luckperms.api.node.types.InheritanceNode;

import java.util.ArrayList;
Expand All @@ -57,11 +61,11 @@

public class GroupListMembers extends ChildCommand<Group> {
public GroupListMembers() {
super(CommandSpec.GROUP_LISTMEMBERS, "listmembers", CommandPermission.GROUP_LIST_MEMBERS, Predicates.notInRange(0, 1));
super(CommandSpec.GROUP_LISTMEMBERS, "listmembers", CommandPermission.GROUP_LIST_MEMBERS, Predicates.notInRange(0, 2));
}

@Override
public void execute(LuckPermsPlugin plugin, Sender sender, Group target, ArgumentList args, String label) {
public void execute(LuckPermsPlugin plugin, Sender sender, Group target, ArgumentList args, String label) throws CommandException {
if (ArgumentPermissions.checkViewPerms(plugin, sender, getPermission().get(), target)) {
Message.COMMAND_NO_PERMISSION.send(sender);
return;
Expand All @@ -70,11 +74,13 @@ public void execute(LuckPermsPlugin plugin, Sender sender, Group target, Argumen
InheritanceNode node = Inheritance.builder(target.getName()).build();
ConstraintNodeMatcher<InheritanceNode> matcher = StandardNodeMatchers.key(node);
int page = args.getIntOrDefault(0, 1);
ImmutableContextSet context = args.getContextOrEmpty(1);

Message.SEARCH_SEARCHING_MEMBERS.send(sender, target.getName());

List<NodeEntry<UUID, InheritanceNode>> matchedUsers = plugin.getStorage().searchUserNodes(matcher).join().stream()
.filter(n -> n.getNode().getValue())
.filter(n -> context.isEmpty() || n.getNode().getContexts().isSatisfiedBy(context))
.collect(Collectors.toList());

// special handling for default group
Expand All @@ -92,6 +98,7 @@ public void execute(LuckPermsPlugin plugin, Sender sender, Group target, Argumen

List<NodeEntry<String, InheritanceNode>> matchedGroups = plugin.getStorage().searchGroupNodes(matcher).join().stream()
.filter(n -> n.getNode().getValue())
.filter(n -> context.isEmpty() || n.getNode().getContexts().isSatisfiedBy(context))
.collect(Collectors.toList());

int users = matchedUsers.size();
Expand Down Expand Up @@ -134,4 +141,11 @@ private static <T extends Comparable<T>> void sendResult(Sender sender, List<Nod
Message.SEARCH_INHERITS_NODE_ENTRY.send(sender, ent.getValue().getNode(), ent.getKey(), holderType, label, sender.getPlugin());
}
}

@Override
public List<String> tabComplete(LuckPermsPlugin plugin, Sender sender, ArgumentList args) {
return TabCompleter.create()
.from(1, TabCompletions.contexts(plugin))
.complete(args);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -705,6 +705,31 @@ private ConfigKeys() {}
*/
public static final ConfigKey<Boolean> REDIS_SSL = notReloadable(booleanKey("redis.ssl", false));

/**
* If redis sentinel is enabled
*/
public static final ConfigKey<Boolean> REDIS_SENTINEL_ENABLED = notReloadable(booleanKey("redis.sentinel.enabled", false));

/**
* The name of the redis sentinel master
*/
public static final ConfigKey<String> REDIS_SENTINEL_MASTER = notReloadable(stringKey("redis.sentinel.master", "mymaster"));

/**
* The addresses of the redis sentinel nodes
*/
public static final ConfigKey<List<String>> REDIS_SENTINEL_ADDRESSES = notReloadable(stringListKey("redis.sentinel.addresses", ImmutableList.of()));

/**
* The username to connect to the redis sentinel nodes with, or an empty string if it should use default
*/
public static final ConfigKey<String> REDIS_SENTINEL_USERNAME = notReloadable(stringKey("redis.sentinel.username", ""));

/**
* The password in use by the redis sentinel nodes, or an empty string if there is no password
*/
public static final ConfigKey<String> REDIS_SENTINEL_PASSWORD = notReloadable(stringKey("redis.sentinel.password", ""));

/**
* If nats messaging is enabled
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,21 @@ private class RedisMessengerProvider implements MessengerProvider {
}
boolean ssl = config.get(ConfigKeys.REDIS_SSL);

if (!addresses.isEmpty()) {
boolean sentinelEnabled = config.get(ConfigKeys.REDIS_SENTINEL_ENABLED);
if (sentinelEnabled) {
// redis sentinel
String masterName = config.get(ConfigKeys.REDIS_SENTINEL_MASTER);
List<String> sentinelAddresses = config.get(ConfigKeys.REDIS_SENTINEL_ADDRESSES);
String sentinelUsername = config.get(ConfigKeys.REDIS_SENTINEL_USERNAME);
String sentinelPassword = config.get(ConfigKeys.REDIS_SENTINEL_PASSWORD);
if (sentinelUsername.isEmpty()) {
sentinelUsername = null;
}
if (sentinelPassword.isEmpty()) {
sentinelPassword = null;
}
redis.init(masterName, sentinelAddresses, username, password, ssl, sentinelUsername, sentinelPassword);
} else if (!addresses.isEmpty()) {
// redis cluster
addresses = new ArrayList<>(addresses);
if (address != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPooled;
import redis.clients.jedis.JedisPubSub;
import redis.clients.jedis.JedisSentineled;
import redis.clients.jedis.Protocol;
import redis.clients.jedis.UnifiedJedis;

Expand All @@ -48,6 +49,7 @@
*/
public class RedisMessenger implements Messenger {
private static final String CHANNEL = "luckperms:update";
private static final int SENTINEL_DEFAULT_PORT = 26379;

private final LuckPermsPlugin plugin;
private final IncomingMessageConsumer consumer;
Expand All @@ -70,6 +72,13 @@ public void init(String address, String username, String password, boolean ssl)
this.init(new JedisPooled(parseAddress(address), jedisConfig(username, password, ssl)));
}

public void init(String masterName, List<String> sentinelAddresses, String username, String password, boolean ssl, String sentinelUsername, String sentinelPassword) {
Set<HostAndPort> sentinels = sentinelAddresses.stream()
.map(addr -> parseAddress(addr, SENTINEL_DEFAULT_PORT))
.collect(Collectors.toSet());
this.init(new JedisSentineled(masterName, jedisConfig(username, password, ssl), sentinels, jedisConfig(sentinelUsername, sentinelPassword, ssl)));
}

private void init(UnifiedJedis jedis) {
this.jedis = jedis;
this.sub = new Subscription(this);
Expand All @@ -86,9 +95,13 @@ private static JedisClientConfig jedisConfig(String username, String password, b
}

private static HostAndPort parseAddress(String address) {
return parseAddress(address, Protocol.DEFAULT_PORT);
}

private static HostAndPort parseAddress(String address, int defaultPort) {
me.lucko.luckperms.common.util.HostAndPort hostAndPort = new me.lucko.luckperms.common.util.HostAndPort(address)
.requireBracketsForIPv6()
.withDefaultPort(Protocol.DEFAULT_PORT);
.withDefaultPort(defaultPort);
String host = hostAndPort.getHost();
int port = hostAndPort.getPort();
return new HostAndPort(host, port);
Expand Down Expand Up @@ -162,6 +175,8 @@ private boolean isRedisAlive() {
return !((JedisPooled) jedis).getPool().isClosed();
} else if (jedis instanceof JedisCluster) {
return !((JedisCluster) jedis).getClusterNodes().isEmpty();
} else if (jedis instanceof JedisSentineled) {
return true;
} else {
throw new RuntimeException("Unknown jedis type: " + jedis.getClass().getName());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ protected AbstractSqlMessenger(IncomingMessageConsumer consumer) {
public void init() throws SQLException {
try (Connection c = getConnection()) {
// init table
String createStatement = "CREATE TABLE IF NOT EXISTS `" + getTableName() + "` (`id` INT AUTO_INCREMENT NOT NULL, `time` TIMESTAMP NOT NULL, `msg` TEXT NOT NULL, PRIMARY KEY (`id`)) DEFAULT CHARSET = utf8mb4";
String createStatement = "CREATE TABLE IF NOT EXISTS `" + getTableName() + "` (`id` INT AUTO_INCREMENT NOT NULL, `time` TIMESTAMP NOT NULL, `msg` TEXT NOT NULL, PRIMARY KEY (`id`), KEY (`time`)) DEFAULT CHARSET = utf8mb4";
try (Statement s = c.createStatement()) {
try {
s.execute(createStatement);
Expand All @@ -73,6 +73,18 @@ public void init() throws SQLException {
}
}

// add index for time column if it doesn't already exist
try (PreparedStatement ps = c.prepareStatement("SELECT 1 FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? AND COLUMN_NAME = 'time' LIMIT 1")) {
ps.setString(1, getTableName());
try (ResultSet rs = ps.executeQuery()) {
if (!rs.next()) {
try (Statement s = c.createStatement()) {
s.execute("CREATE INDEX `time` ON `" + getTableName() + "` (`time`)");
}
}
}
}

// pull last id
try (PreparedStatement ps = c.prepareStatement("SELECT MAX(`id`) as `latest` FROM `" + getTableName() + "`")) {
try (ResultSet rs = ps.executeQuery()) {
Expand Down Expand Up @@ -112,7 +124,7 @@ public void pollMessages() {
}

try (Connection c = getConnection()) {
try (PreparedStatement ps = c.prepareStatement("SELECT `id`, `msg` FROM `" + getTableName() + "` WHERE `id` > ? AND (NOW() - `time` < 30)")) {
try (PreparedStatement ps = c.prepareStatement("SELECT `id`, `msg` FROM `" + getTableName() + "` WHERE `id` > ? AND `time` > (NOW() - INTERVAL 30 SECOND)")) {
ps.setLong(1, this.lastId);
try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
Expand All @@ -139,7 +151,7 @@ public void runHousekeeping() {
}

try (Connection c = getConnection()) {
try (PreparedStatement ps = c.prepareStatement("DELETE FROM `" + getTableName() + "` WHERE (NOW() - `time` > 60)")) {
try (PreparedStatement ps = c.prepareStatement("DELETE FROM `" + getTableName() + "` WHERE `time` < (NOW() - INTERVAL 60 SECOND)")) {
ps.execute();
}
} catch (SQLException e) {
Expand Down
1 change: 1 addition & 0 deletions common/src/main/resources/luckperms_en.properties
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,7 @@ luckperms.usage.user-clone.argument.user=the name/uuid of the user to clone onto
luckperms.usage.group-info.description=Gives info about the group
luckperms.usage.group-listmembers.description=Show the users/groups who inherit from this group
luckperms.usage.group-listmembers.argument.page=the page to view
luckperms.usage.group-listmembers.argument.context=the context to filter members by
luckperms.usage.group-setweight.description=Set the groups weight
luckperms.usage.group-setweight.argument.weight=the weight to set
luckperms.usage.group-set-display-name.description=Set the groups display name
Expand Down
10 changes: 10 additions & 0 deletions fabric/src/main/resources/luckperms.conf
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,16 @@ redis {
address = "localhost"
username = ""
password = ""
# Settings for Redis Sentinel.
# Sentinel provides high availability for Redis by monitoring master/replica instances.
# Port 26379 is used by default for sentinel nodes.
sentinel {
enabled = false
master = "mymaster"
addresses = ["localhost:26379"]
username = ""
password = ""
}
}

# Settings for nats.
Expand Down
10 changes: 10 additions & 0 deletions forge/src/main/resources/luckperms.conf
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,16 @@ redis {
address = "localhost"
username = ""
password = ""
# Settings for Redis Sentinel.
# Sentinel provides high availability for Redis by monitoring master/replica instances.
# Port 26379 is used by default for sentinel nodes.
sentinel {
enabled = false
master = "mymaster"
addresses = ["localhost:26379"]
username = ""
password = ""
}
}

# Settings for nats.
Expand Down
10 changes: 10 additions & 0 deletions neoforge/src/main/resources/luckperms.conf
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,16 @@ redis {
address = "localhost"
username = ""
password = ""
# Settings for Redis Sentinel.
# Sentinel provides high availability for Redis by monitoring master/replica instances.
# Port 26379 is used by default for sentinel nodes.
sentinel {
enabled = false
master = "mymaster"
addresses = ["localhost:26379"]
username = ""
password = ""
}
}

# Settings for nats.
Expand Down
10 changes: 10 additions & 0 deletions nukkit/src/main/resources/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,16 @@ redis:
address: localhost
username: ''
password: ''
# Settings for Redis Sentinel.
# Sentinel provides high availability for Redis by monitoring master/replica instances.
# Port 26379 is used by default for sentinel nodes.
sentinel:
enabled: false
master: mymaster
addresses:
- localhost:26379
username: ''
password: ''

# Settings for Nats.
# Port 4222 is used by default; set address to "host:port" if differs
Expand Down
2 changes: 1 addition & 1 deletion settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pluginManagement {
}

plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version("0.8.0")
id("org.gradle.toolchains.foojay-resolver-convention") version("1.0.0")
}

rootProject.name = 'luckperms'
Expand Down
10 changes: 10 additions & 0 deletions sponge/src/main/resources/luckperms.conf
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,16 @@ redis {
address = "localhost"
username = ""
password = ""
# Settings for Redis Sentinel.
# Sentinel provides high availability for Redis by monitoring master/replica instances.
# Port 26379 is used by default for sentinel nodes.
sentinel {
enabled = false
master = "mymaster"
addresses = ["localhost:26379"]
username = ""
password = ""
}
}

# Settings for nats.
Expand Down
10 changes: 10 additions & 0 deletions standalone/src/main/resources/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,16 @@ redis:
address: localhost
username: ''
password: ''
# Settings for Redis Sentinel.
# Sentinel provides high availability for Redis by monitoring master/replica instances.
# Port 26379 is used by default for sentinel nodes.
sentinel:
enabled: false
master: mymaster
addresses:
- localhost:26379
username: ''
password: ''

# Settings for Nats.
# Port 4222 is used by default; set address to "host:port" if differs
Expand Down
Loading
Loading