Add methods to get a list of users/groups with a specific permission

This commit is contained in:
Luck 2017-01-11 21:25:57 +00:00
parent 1c229d54d9
commit ced3e6959c
No known key found for this signature in database
GPG Key ID: EFA9B3EC5FD90F8B
13 changed files with 487 additions and 21 deletions

View File

@ -33,9 +33,11 @@ import me.lucko.luckperms.common.core.model.Track;
import me.lucko.luckperms.common.core.model.User; import me.lucko.luckperms.common.core.model.User;
import me.lucko.luckperms.common.data.Log; import me.lucko.luckperms.common.data.Log;
import me.lucko.luckperms.common.storage.backing.AbstractBacking; import me.lucko.luckperms.common.storage.backing.AbstractBacking;
import me.lucko.luckperms.common.storage.holder.HeldPermission;
import me.lucko.luckperms.common.storage.wrappings.BufferedOutputStorage; import me.lucko.luckperms.common.storage.wrappings.BufferedOutputStorage;
import me.lucko.luckperms.common.storage.wrappings.TolerantStorage; import me.lucko.luckperms.common.storage.wrappings.TolerantStorage;
import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
@ -94,6 +96,11 @@ public class AbstractStorage implements Storage {
return makeFuture(backing::getUniqueUsers); return makeFuture(backing::getUniqueUsers);
} }
@Override
public CompletableFuture<List<HeldPermission<UUID>>> getUsersWithPermission(String permission) {
return makeFuture(() -> backing.getUsersWithPermission(permission));
}
@Override @Override
public CompletableFuture<Boolean> createAndLoadGroup(String name) { public CompletableFuture<Boolean> createAndLoadGroup(String name) {
return makeFuture(() -> backing.createAndLoadGroup(name)); return makeFuture(() -> backing.createAndLoadGroup(name));
@ -119,6 +126,11 @@ public class AbstractStorage implements Storage {
return makeFuture(() -> backing.deleteGroup(group)); return makeFuture(() -> backing.deleteGroup(group));
} }
@Override
public CompletableFuture<List<HeldPermission<String>>> getGroupsWithPermission(String permission) {
return makeFuture(() -> backing.getGroupsWithPermission(permission));
}
@Override @Override
public CompletableFuture<Boolean> createAndLoadTrack(String name) { public CompletableFuture<Boolean> createAndLoadTrack(String name) {
return makeFuture(() -> backing.createAndLoadTrack(name)); return makeFuture(() -> backing.createAndLoadTrack(name));

View File

@ -31,7 +31,9 @@ import me.lucko.luckperms.common.core.model.Track;
import me.lucko.luckperms.common.core.model.User; import me.lucko.luckperms.common.core.model.User;
import me.lucko.luckperms.common.data.Log; import me.lucko.luckperms.common.data.Log;
import me.lucko.luckperms.common.storage.backing.AbstractBacking; import me.lucko.luckperms.common.storage.backing.AbstractBacking;
import me.lucko.luckperms.common.storage.holder.HeldPermission;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
@ -94,6 +96,11 @@ public class SplitBacking extends AbstractBacking {
return backing.get(types.get("user")).getUniqueUsers(); return backing.get(types.get("user")).getUniqueUsers();
} }
@Override
public List<HeldPermission<UUID>> getUsersWithPermission(String permission) {
return backing.get(types.get("user")).getUsersWithPermission(permission);
}
@Override @Override
public boolean createAndLoadGroup(String name) { public boolean createAndLoadGroup(String name) {
return backing.get(types.get("group")).createAndLoadGroup(name); return backing.get(types.get("group")).createAndLoadGroup(name);
@ -119,6 +126,11 @@ public class SplitBacking extends AbstractBacking {
return backing.get(types.get("group")).deleteGroup(group); return backing.get(types.get("group")).deleteGroup(group);
} }
@Override
public List<HeldPermission<String>> getGroupsWithPermission(String permission) {
return backing.get(types.get("group")).getGroupsWithPermission(permission);
}
@Override @Override
public boolean createAndLoadTrack(String name) { public boolean createAndLoadTrack(String name) {
return backing.get(types.get("track")).createAndLoadTrack(name); return backing.get(types.get("track")).createAndLoadTrack(name);

View File

@ -27,7 +27,9 @@ import me.lucko.luckperms.common.core.model.Group;
import me.lucko.luckperms.common.core.model.Track; import me.lucko.luckperms.common.core.model.Track;
import me.lucko.luckperms.common.core.model.User; import me.lucko.luckperms.common.core.model.User;
import me.lucko.luckperms.common.data.Log; import me.lucko.luckperms.common.data.Log;
import me.lucko.luckperms.common.storage.holder.HeldPermission;
import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
@ -61,6 +63,8 @@ public interface Storage {
CompletableFuture<Set<UUID>> getUniqueUsers(); CompletableFuture<Set<UUID>> getUniqueUsers();
CompletableFuture<List<HeldPermission<UUID>>> getUsersWithPermission(String permission);
CompletableFuture<Boolean> createAndLoadGroup(String name); CompletableFuture<Boolean> createAndLoadGroup(String name);
CompletableFuture<Boolean> loadGroup(String name); CompletableFuture<Boolean> loadGroup(String name);
@ -71,6 +75,8 @@ public interface Storage {
CompletableFuture<Boolean> deleteGroup(Group group); CompletableFuture<Boolean> deleteGroup(Group group);
CompletableFuture<List<HeldPermission<String>>> getGroupsWithPermission(String permission);
CompletableFuture<Boolean> createAndLoadTrack(String name); CompletableFuture<Boolean> createAndLoadTrack(String name);
CompletableFuture<Boolean> loadTrack(String name); CompletableFuture<Boolean> loadTrack(String name);

View File

@ -33,7 +33,9 @@ import me.lucko.luckperms.common.core.model.Group;
import me.lucko.luckperms.common.core.model.Track; import me.lucko.luckperms.common.core.model.Track;
import me.lucko.luckperms.common.core.model.User; import me.lucko.luckperms.common.core.model.User;
import me.lucko.luckperms.common.data.Log; import me.lucko.luckperms.common.data.Log;
import me.lucko.luckperms.common.storage.holder.HeldPermission;
import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
@ -66,6 +68,8 @@ public abstract class AbstractBacking {
public abstract Set<UUID> getUniqueUsers(); public abstract Set<UUID> getUniqueUsers();
public abstract List<HeldPermission<UUID>> getUsersWithPermission(String permission);
public abstract boolean createAndLoadGroup(String name); public abstract boolean createAndLoadGroup(String name);
public abstract boolean loadGroup(String name); public abstract boolean loadGroup(String name);
@ -76,6 +80,8 @@ public abstract class AbstractBacking {
public abstract boolean deleteGroup(Group group); public abstract boolean deleteGroup(Group group);
public abstract List<HeldPermission<String>> getGroupsWithPermission(String permission);
public abstract boolean createAndLoadTrack(String name); public abstract boolean createAndLoadTrack(String name);
public abstract boolean loadTrack(String name); public abstract boolean loadTrack(String name);

View File

@ -22,10 +22,13 @@
package me.lucko.luckperms.common.storage.backing; package me.lucko.luckperms.common.storage.backing;
import com.google.common.collect.ImmutableList;
import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter; import com.google.gson.stream.JsonWriter;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.common.LuckPermsPlugin; import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.core.NodeFactory;
import me.lucko.luckperms.common.core.UserIdentifier; import me.lucko.luckperms.common.core.UserIdentifier;
import me.lucko.luckperms.common.core.model.Group; import me.lucko.luckperms.common.core.model.Group;
import me.lucko.luckperms.common.core.model.Track; import me.lucko.luckperms.common.core.model.Track;
@ -33,6 +36,8 @@ import me.lucko.luckperms.common.core.model.User;
import me.lucko.luckperms.common.managers.GroupManager; import me.lucko.luckperms.common.managers.GroupManager;
import me.lucko.luckperms.common.managers.TrackManager; import me.lucko.luckperms.common.managers.TrackManager;
import me.lucko.luckperms.common.managers.impl.GenericUserManager; import me.lucko.luckperms.common.managers.impl.GenericUserManager;
import me.lucko.luckperms.common.storage.holder.HeldPermission;
import me.lucko.luckperms.common.storage.holder.NodeHeldPermission;
import me.lucko.luckperms.common.utils.ThrowingFunction; import me.lucko.luckperms.common.utils.ThrowingFunction;
import java.io.BufferedReader; import java.io.BufferedReader;
@ -270,6 +275,51 @@ public class JSONBacking extends FlatfileBacking {
.collect(Collectors.toSet()); .collect(Collectors.toSet());
} }
@Override
public List<HeldPermission<UUID>> getUsersWithPermission(String permission) {
ImmutableList.Builder<HeldPermission<UUID>> held = ImmutableList.builder();
boolean success = call(() -> {
File[] files = usersDir.listFiles((dir, name1) -> name1.endsWith(".json"));
if (files == null) return false;
for (File file : files) {
UUID holder = UUID.fromString(file.getName().substring(0, file.getName().length() - 5));
Map<String, Boolean> nodes = new HashMap<>();
fileToReader(file, reader -> {
reader.beginObject();
reader.nextName(); // uuid record
reader.nextString(); // uuid
reader.nextName(); // name record
reader.nextString(); // name
reader.nextName(); // primaryGroup record
reader.nextString(); // primaryGroup
reader.nextName(); //perms
reader.beginObject();
while (reader.hasNext()) {
String node = reader.nextName();
boolean b = reader.nextBoolean();
nodes.put(node, b);
}
reader.endObject();
reader.endObject();
return true;
});
for (Map.Entry<String, Boolean> e : nodes.entrySet()) {
Node node = NodeFactory.fromSerialisedNode(e.getKey(), e.getValue());
if (!node.getPermission().equalsIgnoreCase(permission)) {
continue;
}
held.add(NodeHeldPermission.of(holder, node));
}
}
return true;
}, false);
return success ? held.build() : null;
}
@Override @Override
public boolean createAndLoadGroup(String name) { public boolean createAndLoadGroup(String name) {
Group group = plugin.getGroupManager().getOrMake(name); Group group = plugin.getGroupManager().getOrMake(name);
@ -419,6 +469,47 @@ public class JSONBacking extends FlatfileBacking {
} }
} }
@Override
public List<HeldPermission<String>> getGroupsWithPermission(String permission) {
ImmutableList.Builder<HeldPermission<String>> held = ImmutableList.builder();
boolean success = call(() -> {
File[] files = groupsDir.listFiles((dir, name1) -> name1.endsWith(".json"));
if (files == null) return false;
for (File file : files) {
String holder = file.getName().substring(0, file.getName().length() - 5);
Map<String, Boolean> nodes = new HashMap<>();
fileToReader(file, reader -> {
reader.beginObject();
reader.nextName(); // name record
reader.nextString(); // name
reader.nextName(); // perms
reader.beginObject();
while (reader.hasNext()) {
String node = reader.nextName();
boolean b = reader.nextBoolean();
nodes.put(node, b);
}
reader.endObject();
reader.endObject();
return true;
});
for (Map.Entry<String, Boolean> e : nodes.entrySet()) {
Node node = NodeFactory.fromSerialisedNode(e.getKey(), e.getValue());
if (!node.getPermission().equalsIgnoreCase(permission)) {
continue;
}
held.add(NodeHeldPermission.of(holder, node));
}
}
return true;
}, false);
return success ? held.build() : null;
}
@Override @Override
public boolean createAndLoadTrack(String name) { public boolean createAndLoadTrack(String name) {
Track track = plugin.getTrackManager().getOrMake(name); Track track = plugin.getTrackManager().getOrMake(name);

View File

@ -22,6 +22,7 @@
package me.lucko.luckperms.common.storage.backing; package me.lucko.luckperms.common.storage.backing;
import com.google.common.collect.ImmutableList;
import com.mongodb.MongoClient; import com.mongodb.MongoClient;
import com.mongodb.MongoCredential; import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress; import com.mongodb.ServerAddress;
@ -31,7 +32,9 @@ import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.InsertOneOptions; import com.mongodb.client.model.InsertOneOptions;
import me.lucko.luckperms.api.LogEntry; import me.lucko.luckperms.api.LogEntry;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.common.LuckPermsPlugin; import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.core.NodeFactory;
import me.lucko.luckperms.common.core.UserIdentifier; import me.lucko.luckperms.common.core.UserIdentifier;
import me.lucko.luckperms.common.core.model.Group; import me.lucko.luckperms.common.core.model.Group;
import me.lucko.luckperms.common.core.model.Track; import me.lucko.luckperms.common.core.model.Track;
@ -41,6 +44,8 @@ import me.lucko.luckperms.common.managers.GroupManager;
import me.lucko.luckperms.common.managers.TrackManager; import me.lucko.luckperms.common.managers.TrackManager;
import me.lucko.luckperms.common.managers.impl.GenericUserManager; import me.lucko.luckperms.common.managers.impl.GenericUserManager;
import me.lucko.luckperms.common.storage.DatastoreConfiguration; import me.lucko.luckperms.common.storage.DatastoreConfiguration;
import me.lucko.luckperms.common.storage.holder.HeldPermission;
import me.lucko.luckperms.common.storage.holder.NodeHeldPermission;
import org.bson.Document; import org.bson.Document;
@ -52,6 +57,7 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static me.lucko.luckperms.common.core.model.PermissionHolder.exportToLegacy; import static me.lucko.luckperms.common.core.model.PermissionHolder.exportToLegacy;
@ -71,14 +77,18 @@ public class MongoDBBacking extends AbstractBacking {
/* MongoDB does not allow '.' or '$' in key names. /* MongoDB does not allow '.' or '$' in key names.
See: https://docs.mongodb.com/manual/reference/limits/#Restrictions-on-Field-Names See: https://docs.mongodb.com/manual/reference/limits/#Restrictions-on-Field-Names
The following two methods convert the node maps so they can be stored. */ The following two methods convert the node maps so they can be stored. */
private static final Function<String, String> CONVERT_STRING = s -> s.replace(".", "[**DOT**]").replace("$", "[**DOLLAR**]");
private static final Function<String, String> REVERT_STRING = s -> s.replace("[**DOT**]", ".").replace("[**DOLLAR**]", "$");
private static <V> Map<String, V> convert(Map<String, V> map) { private static <V> Map<String, V> convert(Map<String, V> map) {
return map.entrySet().stream() return map.entrySet().stream()
.collect(Collectors.toMap(e -> e.getKey().replace(".", "[**DOT**]").replace("$", "[**DOLLAR**]"), Map.Entry::getValue)); .collect(Collectors.toMap(e -> CONVERT_STRING.apply(e.getKey()), Map.Entry::getValue));
} }
private static <V> Map<String, V> revert(Map<String, V> map) { private static <V> Map<String, V> revert(Map<String, V> map) {
return map.entrySet().stream() return map.entrySet().stream()
.collect(Collectors.toMap(e -> e.getKey().replace("[**DOT**]", ".").replace("[**DOLLAR**]", "$"), Map.Entry::getValue)); .collect(Collectors.toMap(e -> REVERT_STRING.apply(e.getKey()), Map.Entry::getValue));
} }
private static Document fromUser(User user) { private static Document fromUser(User user) {
@ -315,6 +325,35 @@ public class MongoDBBacking extends AbstractBacking {
return success ? uuids : null; return success ? uuids : null;
} }
@Override
public List<HeldPermission<UUID>> getUsersWithPermission(String permission) {
ImmutableList.Builder<HeldPermission<UUID>> held = ImmutableList.builder();
boolean success = call(() -> {
MongoCollection<Document> c = database.getCollection("users");
try (MongoCursor<Document> cursor = c.find().iterator()) {
while (cursor.hasNext()) {
Document d = cursor.next();
UUID holder = UUID.fromString(d.getString("_id"));
Map<String, Boolean> perms = revert((Map<String, Boolean>) d.get("perms"));
for (Map.Entry<String, Boolean> e : perms.entrySet()) {
Node node = NodeFactory.fromSerialisedNode(e.getKey(), e.getValue());
if (!node.getPermission().equalsIgnoreCase(permission)) {
continue;
}
held.add(NodeHeldPermission.of(holder, node));
}
}
}
return true;
}, false);
return success ? held.build() : null;
}
@Override @Override
public boolean createAndLoadGroup(String name) { public boolean createAndLoadGroup(String name) {
Group group = plugin.getGroupManager().getOrMake(name); Group group = plugin.getGroupManager().getOrMake(name);
@ -419,6 +458,35 @@ public class MongoDBBacking extends AbstractBacking {
return success; return success;
} }
@Override
public List<HeldPermission<String>> getGroupsWithPermission(String permission) {
ImmutableList.Builder<HeldPermission<String>> held = ImmutableList.builder();
boolean success = call(() -> {
MongoCollection<Document> c = database.getCollection("groups");
try (MongoCursor<Document> cursor = c.find().iterator()) {
while (cursor.hasNext()) {
Document d = cursor.next();
String holder = d.getString("_id");
Map<String, Boolean> perms = revert((Map<String, Boolean>) d.get("perms"));
for (Map.Entry<String, Boolean> e : perms.entrySet()) {
Node node = NodeFactory.fromSerialisedNode(e.getKey(), e.getValue());
if (!node.getPermission().equalsIgnoreCase(permission)) {
continue;
}
held.add(NodeHeldPermission.of(holder, node));
}
}
}
return true;
}, false);
return success ? held.build() : null;
}
@Override @Override
public boolean createAndLoadTrack(String name) { public boolean createAndLoadTrack(String name) {
Track track = plugin.getTrackManager().getOrMake(name); Track track = plugin.getTrackManager().getOrMake(name);

View File

@ -24,6 +24,7 @@ package me.lucko.luckperms.common.storage.backing;
import lombok.Getter; import lombok.Getter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
@ -42,6 +43,8 @@ import me.lucko.luckperms.common.managers.impl.GenericUserManager;
import me.lucko.luckperms.common.storage.backing.sqlprovider.SQLProvider; import me.lucko.luckperms.common.storage.backing.sqlprovider.SQLProvider;
import me.lucko.luckperms.common.storage.backing.utils.LegacySchemaMigration; import me.lucko.luckperms.common.storage.backing.utils.LegacySchemaMigration;
import me.lucko.luckperms.common.storage.backing.utils.NodeDataHolder; import me.lucko.luckperms.common.storage.backing.utils.NodeDataHolder;
import me.lucko.luckperms.common.storage.holder.HeldPermission;
import me.lucko.luckperms.common.storage.holder.NodeHeldPermission;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.InputStream; import java.io.InputStream;
@ -72,6 +75,7 @@ public class SQLBacking extends AbstractBacking {
private static final String USER_PERMISSIONS_DELETE = "DELETE FROM {prefix}user_permissions WHERE uuid=?"; private static final String USER_PERMISSIONS_DELETE = "DELETE FROM {prefix}user_permissions WHERE uuid=?";
private static final String USER_PERMISSIONS_INSERT = "INSERT INTO {prefix}user_permissions(uuid, permission, value, server, world, expiry, contexts) VALUES(?, ?, ?, ?, ?, ?, ?)"; private static final String USER_PERMISSIONS_INSERT = "INSERT INTO {prefix}user_permissions(uuid, permission, value, server, world, expiry, contexts) VALUES(?, ?, ?, ?, ?, ?, ?)";
private static final String USER_PERMISSIONS_SELECT_DISTINCT = "SELECT DISTINCT uuid FROM {prefix}user_permissions"; private static final String USER_PERMISSIONS_SELECT_DISTINCT = "SELECT DISTINCT uuid FROM {prefix}user_permissions";
private static final String USER_PERMISSIONS_SELECT_PERMISSION = "SELECT uuid, value, server, world, expiry, contexts FROM {prefix}user_permissions WHERE permission=?";
private static final String PLAYER_SELECT = "SELECT username, primary_group FROM {prefix}players WHERE uuid=?"; private static final String PLAYER_SELECT = "SELECT username, primary_group FROM {prefix}players WHERE uuid=?";
private static final String PLAYER_SELECT_UUID = "SELECT uuid FROM {prefix}players WHERE username=? LIMIT 1"; private static final String PLAYER_SELECT_UUID = "SELECT uuid FROM {prefix}players WHERE username=? LIMIT 1";
@ -85,6 +89,7 @@ public class SQLBacking extends AbstractBacking {
private static final String GROUP_PERMISSIONS_DELETE = "DELETE FROM {prefix}group_permissions WHERE name=?"; private static final String GROUP_PERMISSIONS_DELETE = "DELETE FROM {prefix}group_permissions WHERE name=?";
private static final String GROUP_PERMISSIONS_DELETE_SPECIFIC = "DELETE FROM {prefix}group_permissions WHERE name=? AND permission=? AND value=? AND server=? AND world=? AND expiry=? AND contexts=?"; private static final String GROUP_PERMISSIONS_DELETE_SPECIFIC = "DELETE FROM {prefix}group_permissions WHERE name=? AND permission=? AND value=? AND server=? AND world=? AND expiry=? AND contexts=?";
private static final String GROUP_PERMISSIONS_INSERT = "INSERT INTO {prefix}group_permissions(name, permission, value, server, world, expiry, contexts) VALUES(?, ?, ?, ?, ?, ?, ?)"; private static final String GROUP_PERMISSIONS_INSERT = "INSERT INTO {prefix}group_permissions(name, permission, value, server, world, expiry, contexts) VALUES(?, ?, ?, ?, ?, ?, ?)";
private static final String GROUP_PERMISSIONS_SELECT_PERMISSION = "SELECT name, value, server, world, expiry, contexts FROM {prefix}group_permissions WHERE permission=?";
private static final String GROUP_SELECT_ALL = "SELECT name FROM {prefix}groups"; private static final String GROUP_SELECT_ALL = "SELECT name FROM {prefix}groups";
private static final String GROUP_INSERT = "INSERT INTO {prefix}groups VALUES(?)"; private static final String GROUP_INSERT = "INSERT INTO {prefix}groups VALUES(?)";
@ -404,7 +409,7 @@ public class SQLBacking extends AbstractBacking {
ps.setString(4, nd.getServer()); ps.setString(4, nd.getServer());
ps.setString(5, nd.getWorld()); ps.setString(5, nd.getWorld());
ps.setLong(6, nd.getExpiry()); ps.setLong(6, nd.getExpiry());
ps.setString(7, nd.getContexts()); ps.setString(7, nd.serialiseContext());
ps.addBatch(); ps.addBatch();
} }
ps.executeBatch(); ps.executeBatch();
@ -425,7 +430,7 @@ public class SQLBacking extends AbstractBacking {
ps.setString(4, nd.getServer()); ps.setString(4, nd.getServer());
ps.setString(5, nd.getWorld()); ps.setString(5, nd.getWorld());
ps.setLong(6, nd.getExpiry()); ps.setLong(6, nd.getExpiry());
ps.setString(7, nd.getContexts()); ps.setString(7, nd.serialiseContext());
ps.addBatch(); ps.addBatch();
} }
ps.executeBatch(); ps.executeBatch();
@ -509,6 +514,33 @@ public class SQLBacking extends AbstractBacking {
return uuids; return uuids;
} }
@Override
public List<HeldPermission<UUID>> getUsersWithPermission(String permission) {
ImmutableList.Builder<HeldPermission<UUID>> held = ImmutableList.builder();
try (Connection c = provider.getConnection()) {
try (PreparedStatement ps = c.prepareStatement(prefix.apply(USER_PERMISSIONS_SELECT_PERMISSION))) {
ps.setString(1, permission);
try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
UUID holder = UUID.fromString(rs.getString("uuid"));
boolean value = rs.getBoolean("value");
String server = rs.getString("server");
String world = rs.getString("world");
long expiry = rs.getLong("expiry");
String contexts = rs.getString("contexts");
NodeDataHolder data = NodeDataHolder.of(permission, value, server, world, expiry, contexts);
held.add(NodeHeldPermission.of(holder, data));
}
}
}
} catch (SQLException e) {
e.printStackTrace();
return null;
}
return held.build();
}
@Override @Override
public boolean createAndLoadGroup(String name) { public boolean createAndLoadGroup(String name) {
List<String> groups = new ArrayList<>(); List<String> groups = new ArrayList<>();
@ -692,7 +724,7 @@ public class SQLBacking extends AbstractBacking {
ps.setString(4, nd.getServer()); ps.setString(4, nd.getServer());
ps.setString(5, nd.getWorld()); ps.setString(5, nd.getWorld());
ps.setLong(6, nd.getExpiry()); ps.setLong(6, nd.getExpiry());
ps.setString(7, nd.getContexts()); ps.setString(7, nd.serialiseContext());
ps.addBatch(); ps.addBatch();
} }
ps.executeBatch(); ps.executeBatch();
@ -713,7 +745,7 @@ public class SQLBacking extends AbstractBacking {
ps.setString(4, nd.getServer()); ps.setString(4, nd.getServer());
ps.setString(5, nd.getWorld()); ps.setString(5, nd.getWorld());
ps.setLong(6, nd.getExpiry()); ps.setLong(6, nd.getExpiry());
ps.setString(7, nd.getContexts()); ps.setString(7, nd.serialiseContext());
ps.addBatch(); ps.addBatch();
} }
ps.executeBatch(); ps.executeBatch();
@ -756,6 +788,33 @@ public class SQLBacking extends AbstractBacking {
} }
} }
@Override
public List<HeldPermission<String>> getGroupsWithPermission(String permission) {
ImmutableList.Builder<HeldPermission<String>> held = ImmutableList.builder();
try (Connection c = provider.getConnection()) {
try (PreparedStatement ps = c.prepareStatement(prefix.apply(GROUP_PERMISSIONS_SELECT_PERMISSION))) {
ps.setString(1, permission);
try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
String holder = rs.getString("name");
boolean value = rs.getBoolean("value");
String server = rs.getString("server");
String world = rs.getString("world");
long expiry = rs.getLong("expiry");
String contexts = rs.getString("contexts");
NodeDataHolder data = NodeDataHolder.of(permission, value, server, world, expiry, contexts);
held.add(NodeHeldPermission.of(holder, data));
}
}
}
} catch (SQLException e) {
e.printStackTrace();
return null;
}
return held.build();
}
@Override @Override
public boolean createAndLoadTrack(String name) { public boolean createAndLoadTrack(String name) {
Track track = plugin.getTrackManager().getOrMake(name); Track track = plugin.getTrackManager().getOrMake(name);

View File

@ -22,7 +22,11 @@
package me.lucko.luckperms.common.storage.backing; package me.lucko.luckperms.common.storage.backing;
import com.google.common.collect.ImmutableList;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.common.LuckPermsPlugin; import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.core.NodeFactory;
import me.lucko.luckperms.common.core.UserIdentifier; import me.lucko.luckperms.common.core.UserIdentifier;
import me.lucko.luckperms.common.core.model.Group; import me.lucko.luckperms.common.core.model.Group;
import me.lucko.luckperms.common.core.model.Track; import me.lucko.luckperms.common.core.model.Track;
@ -30,6 +34,8 @@ import me.lucko.luckperms.common.core.model.User;
import me.lucko.luckperms.common.managers.GroupManager; import me.lucko.luckperms.common.managers.GroupManager;
import me.lucko.luckperms.common.managers.TrackManager; import me.lucko.luckperms.common.managers.TrackManager;
import me.lucko.luckperms.common.managers.impl.GenericUserManager; import me.lucko.luckperms.common.managers.impl.GenericUserManager;
import me.lucko.luckperms.common.storage.holder.HeldPermission;
import me.lucko.luckperms.common.storage.holder.NodeHeldPermission;
import org.yaml.snakeyaml.DumperOptions; import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.Yaml;
@ -226,6 +232,36 @@ public class YAMLBacking extends FlatfileBacking {
.collect(Collectors.toSet()); .collect(Collectors.toSet());
} }
@Override
public List<HeldPermission<UUID>> getUsersWithPermission(String permission) {
ImmutableList.Builder<HeldPermission<UUID>> held = ImmutableList.builder();
boolean success = call(() -> {
File[] files = usersDir.listFiles((dir, name1) -> name1.endsWith(".yml"));
if (files == null) return false;
for (File file : files) {
UUID holder = UUID.fromString(file.getName().substring(0, file.getName().length() - 4));
Map<String, Boolean> nodes = new HashMap<>();
readMapFromFile(file, values -> {
Map<String, Boolean> perms = (Map<String, Boolean>) values.get("perms");
nodes.putAll(perms);
return true;
});
for (Map.Entry<String, Boolean> e : nodes.entrySet()) {
Node node = NodeFactory.fromSerialisedNode(e.getKey(), e.getValue());
if (!node.getPermission().equalsIgnoreCase(permission)) {
continue;
}
held.add(NodeHeldPermission.of(holder, node));
}
}
return true;
}, false);
return success ? held.build() : null;
}
@Override @Override
public boolean createAndLoadGroup(String name) { public boolean createAndLoadGroup(String name) {
Group group = plugin.getGroupManager().getOrMake(name); Group group = plugin.getGroupManager().getOrMake(name);
@ -335,6 +371,36 @@ public class YAMLBacking extends FlatfileBacking {
} }
} }
@Override
public List<HeldPermission<String>> getGroupsWithPermission(String permission) {
ImmutableList.Builder<HeldPermission<String>> held = ImmutableList.builder();
boolean success = call(() -> {
File[] files = groupsDir.listFiles((dir, name1) -> name1.endsWith(".yml"));
if (files == null) return false;
for (File file : files) {
String holder = file.getName().substring(0, file.getName().length() - 4);
Map<String, Boolean> nodes = new HashMap<>();
readMapFromFile(file, values -> {
Map<String, Boolean> perms = (Map<String, Boolean>) values.get("perms");
nodes.putAll(perms);
return true;
});
for (Map.Entry<String, Boolean> e : nodes.entrySet()) {
Node node = NodeFactory.fromSerialisedNode(e.getKey(), e.getValue());
if (!node.getPermission().equalsIgnoreCase(permission)) {
continue;
}
held.add(NodeHeldPermission.of(holder, node));
}
}
return true;
}, false);
return success ? held.build() : null;
}
@Override @Override
public boolean createAndLoadTrack(String name) { public boolean createAndLoadTrack(String name) {
Track track = plugin.getTrackManager().getOrMake(name); Track track = plugin.getTrackManager().getOrMake(name);

View File

@ -161,7 +161,7 @@ public class LegacySchemaMigration implements Runnable {
ps.setString(4, nd.getServer()); ps.setString(4, nd.getServer());
ps.setString(5, nd.getWorld()); ps.setString(5, nd.getWorld());
ps.setLong(6, nd.getExpiry()); ps.setLong(6, nd.getExpiry());
ps.setString(7, nd.getContexts()); ps.setString(7, nd.serialiseContext());
ps.addBatch(); ps.addBatch();
} }
ps.executeBatch(); ps.executeBatch();
@ -240,7 +240,7 @@ public class LegacySchemaMigration implements Runnable {
ps.setString(4, nd.getServer()); ps.setString(4, nd.getServer());
ps.setString(5, nd.getWorld()); ps.setString(5, nd.getWorld());
ps.setLong(6, nd.getExpiry()); ps.setLong(6, nd.getExpiry());
ps.setString(7, nd.getContexts()); ps.setString(7, nd.serialiseContext());
ps.addBatch(); ps.addBatch();
} }
ps.executeBatch(); ps.executeBatch();

View File

@ -27,6 +27,8 @@ import lombok.EqualsAndHashCode;
import lombok.Getter; import lombok.Getter;
import lombok.ToString; import lombok.ToString;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
@ -52,16 +54,30 @@ public class NodeDataHolder {
node.getServer().orElse("global"), node.getServer().orElse("global"),
node.getWorld().orElse("global"), node.getWorld().orElse("global"),
node.isTemporary() ? node.getExpiryUnixTime() : 0L, node.isTemporary() ? node.getExpiryUnixTime() : 0L,
GSON.toJson(node.getContexts().toMultimap().asMap()) node.getContexts().toMultimap()
); );
} }
public static NodeDataHolder of(String permission, boolean value, String server, String world, long expiry, String contexts) {
Map<String, Collection<String>> deserializedContexts = GSON.fromJson(contexts, CONTEXT_TYPE);
Multimap<String, String> map = HashMultimap.create();
for (Map.Entry<String, Collection<String>> e : deserializedContexts.entrySet()) {
map.putAll(e.getKey(), e.getValue());
}
return new NodeDataHolder(permission, value, server, world, expiry, map);
}
private final String permission; private final String permission;
private final boolean value; private final boolean value;
private final String server; private final String server;
private final String world; private final String world;
private final long expiry; private final long expiry;
private final String contexts; private final Multimap<String, String> contexts;
public String serialiseContext() {
return GSON.toJson(getContexts().asMap());
}
public Node toNode() { public Node toNode() {
NodeBuilder builder = new NodeBuilder(permission); NodeBuilder builder = new NodeBuilder(permission);
@ -70,17 +86,8 @@ public class NodeDataHolder {
builder.setWorld(world); builder.setWorld(world);
builder.setExpiry(expiry); builder.setExpiry(expiry);
try { for (Map.Entry<String, String> e : contexts.entries()) {
Map<String, Collection<String>> deserializedContexts = GSON.fromJson(contexts, CONTEXT_TYPE); builder.withExtraContext(e);
if (deserializedContexts != null && !deserializedContexts.isEmpty()) {
for (Map.Entry<String, Collection<String>> c : deserializedContexts.entrySet()) {
for (String val : c.getValue()) {
builder.withExtraContext(c.getKey(), val);
}
}
}
} catch (Exception e) {
e.printStackTrace();
} }
return builder.build(); return builder.build();

View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.common.storage.holder;
import com.google.common.collect.Multimap;
import java.util.Optional;
import java.util.OptionalLong;
public interface HeldPermission<T> {
T getHolder();
String getPermission();
boolean getValue();
Optional<String> getServer();
Optional<String> getWorld();
OptionalLong getExpiry();
Multimap<String, String> getContext();
}

View File

@ -0,0 +1,77 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.common.storage.holder;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import com.google.common.collect.Multimap;
import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.common.storage.backing.utils.NodeDataHolder;
import java.util.Optional;
import java.util.OptionalLong;
@Getter
@EqualsAndHashCode
@AllArgsConstructor(staticName = "of")
public class NodeHeldPermission<T> implements HeldPermission<T> {
public static <T> NodeHeldPermission<T> of(T holder, NodeDataHolder nodeDataHolder) {
return of(holder, nodeDataHolder.toNode());
}
private final T holder;
private final Node node;
@Override
public String getPermission() {
return node.getPermission();
}
@Override
public boolean getValue() {
return node.getValue();
}
@Override
public Optional<String> getServer() {
return node.getServer();
}
@Override
public Optional<String> getWorld() {
return node.getWorld();
}
@Override
public OptionalLong getExpiry() {
return node.isTemporary() ? OptionalLong.of(node.getExpiryUnixTime()) : OptionalLong.empty();
}
@Override
public Multimap<String, String> getContext() {
return node.getContexts().toMultimap();
}
}

View File

@ -32,7 +32,9 @@ import me.lucko.luckperms.common.core.model.Track;
import me.lucko.luckperms.common.core.model.User; import me.lucko.luckperms.common.core.model.User;
import me.lucko.luckperms.common.data.Log; import me.lucko.luckperms.common.data.Log;
import me.lucko.luckperms.common.storage.Storage; import me.lucko.luckperms.common.storage.Storage;
import me.lucko.luckperms.common.storage.holder.HeldPermission;
import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
@ -131,6 +133,16 @@ public class TolerantStorage implements Storage {
} }
} }
@Override
public CompletableFuture<List<HeldPermission<UUID>>> getUsersWithPermission(String permission) {
phaser.register();
try {
return backing.getUsersWithPermission(permission);
} finally {
phaser.arriveAndDeregister();
}
}
@Override @Override
public CompletableFuture<Boolean> createAndLoadGroup(String name) { public CompletableFuture<Boolean> createAndLoadGroup(String name) {
phaser.register(); phaser.register();
@ -181,6 +193,16 @@ public class TolerantStorage implements Storage {
} }
} }
@Override
public CompletableFuture<List<HeldPermission<String>>> getGroupsWithPermission(String permission) {
phaser.register();
try {
return backing.getGroupsWithPermission(permission);
} finally {
phaser.arriveAndDeregister();
}
}
@Override @Override
public CompletableFuture<Boolean> createAndLoadTrack(String name) { public CompletableFuture<Boolean> createAndLoadTrack(String name) {
phaser.register(); phaser.register();