mirror of
https://github.com/LuckPerms/LuckPerms.git
synced 2024-11-28 05:35:26 +01:00
Rewrite the MongoDB storage impl to use the modern node serialisation format
This commit is contained in:
parent
c369ac6b90
commit
003ddc51de
@ -74,36 +74,6 @@ public class LegacyNodeFactory {
|
|||||||
private static final Splitter.MapSplitter LEGACY_CONTEXT_PART_SPLITTER = Splitter.on(LEGACY_CONTEXT_PAIR_DELIM)
|
private static final Splitter.MapSplitter LEGACY_CONTEXT_PART_SPLITTER = Splitter.on(LEGACY_CONTEXT_PAIR_DELIM)
|
||||||
.withKeyValueSeparator(Splitter.on(LEGACY_CONTEXT_PAIR_PART_DELIM));
|
.withKeyValueSeparator(Splitter.on(LEGACY_CONTEXT_PAIR_PART_DELIM));
|
||||||
|
|
||||||
public static String toSerializedNode(Node node) {
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
|
|
||||||
if (node.getServer().orElse(null) != null) {
|
|
||||||
builder.append(escapeDelimiters(node.getServer().orElse(null), SERVER_WORLD_DELIMITERS));
|
|
||||||
if (node.getWorld().orElse(null) != null) {
|
|
||||||
builder.append("-").append(escapeDelimiters(node.getWorld().orElse(null), SERVER_WORLD_DELIMITERS));
|
|
||||||
}
|
|
||||||
builder.append("/");
|
|
||||||
} else {
|
|
||||||
if (node.getWorld().orElse(null) != null) {
|
|
||||||
builder.append("global-").append(escapeDelimiters(node.getWorld().orElse(null), SERVER_WORLD_DELIMITERS)).append("/");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!node.getContexts().isEmpty()) {
|
|
||||||
builder.append("(");
|
|
||||||
for (Map.Entry<String, String> entry : node.getContexts().toSet()) {
|
|
||||||
builder.append(escapeDelimiters(entry.getKey(), CONTEXT_DELIMITERS))
|
|
||||||
.append("=").append(escapeDelimiters(entry.getValue(), CONTEXT_DELIMITERS)).append(",");
|
|
||||||
}
|
|
||||||
builder.deleteCharAt(builder.length() - 1);
|
|
||||||
builder.append(")");
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.append(escapeDelimiters(node.getPermission(), PERMISSION_DELIMITERS));
|
|
||||||
if (node.isTemporary()) builder.append("$").append(node.getExpiryUnixTime());
|
|
||||||
return builder.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Node fromLegacyString(String s, boolean b) {
|
public static Node fromLegacyString(String s, boolean b) {
|
||||||
if (b) {
|
if (b) {
|
||||||
return builderFromLegacyString(s, true).build();
|
return builderFromLegacyString(s, true).build();
|
||||||
|
@ -394,8 +394,7 @@ public abstract class ConfigurateDao extends AbstractDao {
|
|||||||
String name = object.getNode("name").getString();
|
String name = object.getNode("name").getString();
|
||||||
user.getPrimaryGroup().setStoredValue(object.getNode(this instanceof JsonDao ? "primaryGroup" : "primary-group").getString());
|
user.getPrimaryGroup().setStoredValue(object.getNode(this instanceof JsonDao ? "primaryGroup" : "primary-group").getString());
|
||||||
|
|
||||||
Set<NodeModel> data = readNodes(object);
|
Set<Node> nodes = readNodes(object).stream().map(NodeModel::toNode).collect(Collectors.toSet());
|
||||||
Set<Node> nodes = data.stream().map(NodeModel::toNode).collect(Collectors.toSet());
|
|
||||||
user.setEnduringNodes(nodes);
|
user.setEnduringNodes(nodes);
|
||||||
user.setName(name, true);
|
user.setName(name, true);
|
||||||
|
|
||||||
@ -498,8 +497,7 @@ public abstract class ConfigurateDao extends AbstractDao {
|
|||||||
ConfigurationNode object = readFile(StorageLocation.GROUP, name);
|
ConfigurationNode object = readFile(StorageLocation.GROUP, name);
|
||||||
|
|
||||||
if (object != null) {
|
if (object != null) {
|
||||||
Set<NodeModel> data = readNodes(object);
|
Set<Node> nodes = readNodes(object).stream().map(NodeModel::toNode).collect(Collectors.toSet());
|
||||||
Set<Node> nodes = data.stream().map(NodeModel::toNode).collect(Collectors.toSet());
|
|
||||||
group.setEnduringNodes(nodes);
|
group.setEnduringNodes(nodes);
|
||||||
} else {
|
} else {
|
||||||
ConfigurationNode data = SimpleConfigurationNode.root();
|
ConfigurationNode data = SimpleConfigurationNode.root();
|
||||||
|
@ -27,6 +27,7 @@ package me.lucko.luckperms.common.storage.dao.mongodb;
|
|||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import com.google.common.base.Strings;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.mongodb.MongoClient;
|
import com.mongodb.MongoClient;
|
||||||
import com.mongodb.MongoCredential;
|
import com.mongodb.MongoCredential;
|
||||||
@ -34,11 +35,14 @@ import com.mongodb.ServerAddress;
|
|||||||
import com.mongodb.client.MongoCollection;
|
import com.mongodb.client.MongoCollection;
|
||||||
import com.mongodb.client.MongoCursor;
|
import com.mongodb.client.MongoCursor;
|
||||||
import com.mongodb.client.MongoDatabase;
|
import com.mongodb.client.MongoDatabase;
|
||||||
import com.mongodb.client.model.InsertOneOptions;
|
import com.mongodb.client.model.UpdateOptions;
|
||||||
|
|
||||||
import me.lucko.luckperms.api.HeldPermission;
|
import me.lucko.luckperms.api.HeldPermission;
|
||||||
import me.lucko.luckperms.api.LogEntry;
|
import me.lucko.luckperms.api.LogEntry;
|
||||||
import me.lucko.luckperms.api.Node;
|
import me.lucko.luckperms.api.Node;
|
||||||
|
import me.lucko.luckperms.api.context.ContextSet;
|
||||||
|
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||||
|
import me.lucko.luckperms.api.context.MutableContextSet;
|
||||||
import me.lucko.luckperms.common.actionlog.ExtendedLogEntry;
|
import me.lucko.luckperms.common.actionlog.ExtendedLogEntry;
|
||||||
import me.lucko.luckperms.common.actionlog.Log;
|
import me.lucko.luckperms.common.actionlog.Log;
|
||||||
import me.lucko.luckperms.common.bulkupdate.BulkUpdate;
|
import me.lucko.luckperms.common.bulkupdate.BulkUpdate;
|
||||||
@ -60,7 +64,6 @@ import org.bson.Document;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -68,10 +71,8 @@ import java.util.Map;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public class MongoDao extends AbstractDao {
|
public class MongoDao extends AbstractDao {
|
||||||
|
|
||||||
private final StorageCredentials configuration;
|
private final StorageCredentials configuration;
|
||||||
@ -96,21 +97,13 @@ public class MongoDao extends AbstractDao {
|
|||||||
@Override
|
@Override
|
||||||
public void init() {
|
public void init() {
|
||||||
MongoCredential credential = null;
|
MongoCredential credential = null;
|
||||||
|
if (!Strings.isNullOrEmpty(configuration.getUsername())) {
|
||||||
if (configuration.getUsername() != null && !configuration.getUsername().equals("") && configuration.getDatabase() != null && !configuration.getDatabase().equals("")) {
|
|
||||||
if (configuration.getPassword() == null || configuration.getPassword().equals("")) {
|
|
||||||
credential = MongoCredential.createCredential(
|
|
||||||
configuration.getUsername(),
|
|
||||||
configuration.getDatabase(), null
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
credential = MongoCredential.createCredential(
|
credential = MongoCredential.createCredential(
|
||||||
configuration.getUsername(),
|
configuration.getUsername(),
|
||||||
configuration.getDatabase(),
|
configuration.getDatabase(),
|
||||||
configuration.getPassword().toCharArray()
|
Strings.isNullOrEmpty(configuration.getPassword()) ? null : configuration.getPassword().toCharArray()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
String[] addressSplit = configuration.getAddress().split(":");
|
String[] addressSplit = configuration.getAddress().split(":");
|
||||||
String host = addressSplit[0];
|
String host = addressSplit[0];
|
||||||
@ -161,7 +154,6 @@ public class MongoDao extends AbstractDao {
|
|||||||
public boolean logAction(LogEntry entry) {
|
public boolean logAction(LogEntry entry) {
|
||||||
try {
|
try {
|
||||||
MongoCollection<Document> c = database.getCollection(prefix + "action");
|
MongoCollection<Document> c = database.getCollection(prefix + "action");
|
||||||
|
|
||||||
Document doc = new Document()
|
Document doc = new Document()
|
||||||
.append("timestamp", entry.getTimestamp())
|
.append("timestamp", entry.getTimestamp())
|
||||||
.append("actor", entry.getActor())
|
.append("actor", entry.getActor())
|
||||||
@ -174,7 +166,7 @@ public class MongoDao extends AbstractDao {
|
|||||||
doc.append("acted", entry.getActed().get());
|
doc.append("acted", entry.getActed().get());
|
||||||
}
|
}
|
||||||
|
|
||||||
c.insertOne(doc, new InsertOneOptions());
|
c.insertOne(doc);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return reportException(e);
|
return reportException(e);
|
||||||
}
|
}
|
||||||
@ -186,7 +178,6 @@ public class MongoDao extends AbstractDao {
|
|||||||
Log.Builder log = Log.builder();
|
Log.Builder log = Log.builder();
|
||||||
try {
|
try {
|
||||||
MongoCollection<Document> c = database.getCollection(prefix + "action");
|
MongoCollection<Document> c = database.getCollection(prefix + "action");
|
||||||
|
|
||||||
try (MongoCursor<Document> cursor = c.find().iterator()) {
|
try (MongoCursor<Document> cursor = c.find().iterator()) {
|
||||||
while (cursor.hasNext()) {
|
while (cursor.hasNext()) {
|
||||||
Document d = cursor.next();
|
Document d = cursor.next();
|
||||||
@ -221,33 +212,23 @@ public class MongoDao extends AbstractDao {
|
|||||||
try {
|
try {
|
||||||
if (bulkUpdate.getDataType().isIncludingUsers()) {
|
if (bulkUpdate.getDataType().isIncludingUsers()) {
|
||||||
MongoCollection<Document> c = database.getCollection(prefix + "users");
|
MongoCollection<Document> c = database.getCollection(prefix + "users");
|
||||||
|
|
||||||
try (MongoCursor<Document> cursor = c.find().iterator()) {
|
try (MongoCursor<Document> cursor = c.find().iterator()) {
|
||||||
while (cursor.hasNext()) {
|
while (cursor.hasNext()) {
|
||||||
Document d = cursor.next();
|
Document d = cursor.next();
|
||||||
|
|
||||||
UUID uuid = d.get("_id", UUID.class);
|
UUID uuid = d.get("_id", UUID.class);
|
||||||
Map<String, Boolean> perms = revert((Map<String, Boolean>) d.get("perms"));
|
Set<NodeModel> nodes = new HashSet<>(nodesFromDoc(d));
|
||||||
|
|
||||||
Set<NodeModel> nodes = new HashSet<>();
|
|
||||||
for (Map.Entry<String, Boolean> e : perms.entrySet()) {
|
|
||||||
Node node = LegacyNodeFactory.fromLegacyString(e.getKey(), e.getValue());
|
|
||||||
nodes.add(NodeModel.fromNode(node));
|
|
||||||
}
|
|
||||||
|
|
||||||
Set<NodeModel> results = nodes.stream()
|
Set<NodeModel> results = nodes.stream()
|
||||||
.map(bulkUpdate::apply)
|
.map(bulkUpdate::apply)
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
if (!nodes.equals(results)) {
|
if (!nodes.equals(results)) {
|
||||||
Document permsDoc = new Document();
|
List<Document> newNodes = results.stream()
|
||||||
for (Map.Entry<String, Boolean> e : convert(exportToLegacy(results.stream().map(NodeModel::toNode).collect(Collectors.toList()))).entrySet()) {
|
.map(MongoDao::nodeToDoc)
|
||||||
permsDoc.append(e.getKey(), e.getValue());
|
.collect(Collectors.toList());
|
||||||
}
|
|
||||||
|
|
||||||
d.put("perms", permsDoc);
|
c.replaceOne(new Document("_id", uuid), d.append("permissions", newNodes));
|
||||||
c.replaceOne(new Document("_id", uuid), d);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -255,33 +236,23 @@ public class MongoDao extends AbstractDao {
|
|||||||
|
|
||||||
if (bulkUpdate.getDataType().isIncludingGroups()) {
|
if (bulkUpdate.getDataType().isIncludingGroups()) {
|
||||||
MongoCollection<Document> c = database.getCollection(prefix + "groups");
|
MongoCollection<Document> c = database.getCollection(prefix + "groups");
|
||||||
|
|
||||||
try (MongoCursor<Document> cursor = c.find().iterator()) {
|
try (MongoCursor<Document> cursor = c.find().iterator()) {
|
||||||
while (cursor.hasNext()) {
|
while (cursor.hasNext()) {
|
||||||
Document d = cursor.next();
|
Document d = cursor.next();
|
||||||
|
|
||||||
String holder = d.getString("_id");
|
String holder = d.getString("_id");
|
||||||
Map<String, Boolean> perms = revert((Map<String, Boolean>) d.get("perms"));
|
Set<NodeModel> nodes = new HashSet<>(nodesFromDoc(d));
|
||||||
|
|
||||||
Set<NodeModel> nodes = new HashSet<>();
|
|
||||||
for (Map.Entry<String, Boolean> e : perms.entrySet()) {
|
|
||||||
Node node = LegacyNodeFactory.fromLegacyString(e.getKey(), e.getValue());
|
|
||||||
nodes.add(NodeModel.fromNode(node));
|
|
||||||
}
|
|
||||||
|
|
||||||
Set<NodeModel> results = nodes.stream()
|
Set<NodeModel> results = nodes.stream()
|
||||||
.map(bulkUpdate::apply)
|
.map(bulkUpdate::apply)
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
if (!nodes.equals(results)) {
|
if (!nodes.equals(results)) {
|
||||||
Document permsDoc = new Document();
|
List<Document> newNodes = results.stream()
|
||||||
for (Map.Entry<String, Boolean> e : convert(exportToLegacy(results.stream().map(NodeModel::toNode).collect(Collectors.toList()))).entrySet()) {
|
.map(MongoDao::nodeToDoc)
|
||||||
permsDoc.append(e.getKey(), e.getValue());
|
.collect(Collectors.toList());
|
||||||
}
|
|
||||||
|
|
||||||
d.put("perms", permsDoc);
|
c.replaceOne(new Document("_id", holder), d.append("permissions", newNodes));
|
||||||
c.replaceOne(new Document("_id", holder), d);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -299,17 +270,16 @@ public class MongoDao extends AbstractDao {
|
|||||||
user.getIoLock().lock();
|
user.getIoLock().lock();
|
||||||
try {
|
try {
|
||||||
MongoCollection<Document> c = database.getCollection(prefix + "users");
|
MongoCollection<Document> c = database.getCollection(prefix + "users");
|
||||||
|
|
||||||
try (MongoCursor<Document> cursor = c.find(new Document("_id", user.getUuid())).iterator()) {
|
try (MongoCursor<Document> cursor = c.find(new Document("_id", user.getUuid())).iterator()) {
|
||||||
if (cursor.hasNext()) {
|
if (cursor.hasNext()) {
|
||||||
// User exists, let's load.
|
// User exists, let's load.
|
||||||
Document d = cursor.next();
|
Document d = cursor.next();
|
||||||
user.setEnduringNodes(revert((Map<String, Boolean>) d.get("perms")).entrySet().stream()
|
|
||||||
.map(e -> LegacyNodeFactory.fromLegacyString(e.getKey(), e.getValue()))
|
|
||||||
.collect(Collectors.toSet())
|
|
||||||
);
|
|
||||||
user.getPrimaryGroup().setStoredValue(d.getString("primaryGroup"));
|
user.getPrimaryGroup().setStoredValue(d.getString("primaryGroup"));
|
||||||
user.setName(name, true);
|
user.setName(d.getString("name"), true);
|
||||||
|
|
||||||
|
Set<Node> nodes = nodesFromDoc(d).stream().map(NodeModel::toNode).collect(Collectors.toSet());
|
||||||
|
user.setEnduringNodes(nodes);
|
||||||
|
|
||||||
boolean save = plugin.getUserManager().giveDefaultIfNeeded(user, false);
|
boolean save = plugin.getUserManager().giveDefaultIfNeeded(user, false);
|
||||||
if (user.getName().isPresent() && (name == null || !user.getName().get().equalsIgnoreCase(name))) {
|
if (user.getName().isPresent() && (name == null || !user.getName().get().equalsIgnoreCase(name))) {
|
||||||
@ -317,7 +287,7 @@ public class MongoDao extends AbstractDao {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (save) {
|
if (save) {
|
||||||
c.replaceOne(new Document("_id", user.getUuid()), fromUser(user));
|
c.replaceOne(new Document("_id", user.getUuid()), userToDoc(user));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (GenericUserManager.shouldSave(user)) {
|
if (GenericUserManager.shouldSave(user)) {
|
||||||
@ -340,25 +310,17 @@ public class MongoDao extends AbstractDao {
|
|||||||
public boolean saveUser(User user) {
|
public boolean saveUser(User user) {
|
||||||
user.getIoLock().lock();
|
user.getIoLock().lock();
|
||||||
try {
|
try {
|
||||||
|
MongoCollection<Document> c = database.getCollection(prefix + "users");
|
||||||
if (!GenericUserManager.shouldSave(user)) {
|
if (!GenericUserManager.shouldSave(user)) {
|
||||||
MongoCollection<Document> c = database.getCollection(prefix + "users");
|
|
||||||
return c.deleteOne(new Document("_id", user.getUuid())).wasAcknowledged();
|
return c.deleteOne(new Document("_id", user.getUuid())).wasAcknowledged();
|
||||||
}
|
|
||||||
|
|
||||||
MongoCollection<Document> c = database.getCollection(prefix + "users");
|
|
||||||
try (MongoCursor<Document> cursor = c.find(new Document("_id", user.getUuid())).iterator()) {
|
|
||||||
if (!cursor.hasNext()) {
|
|
||||||
c.insertOne(fromUser(user));
|
|
||||||
} else {
|
} else {
|
||||||
c.replaceOne(new Document("_id", user.getUuid()), fromUser(user));
|
return c.replaceOne(new Document("_id", user.getUuid()), userToDoc(user), new UpdateOptions().upsert(true)).wasAcknowledged();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return reportException(e);
|
return reportException(e);
|
||||||
} finally {
|
} finally {
|
||||||
user.getIoLock().unlock();
|
user.getIoLock().unlock();
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -366,7 +328,6 @@ public class MongoDao extends AbstractDao {
|
|||||||
Set<UUID> uuids = new HashSet<>();
|
Set<UUID> uuids = new HashSet<>();
|
||||||
try {
|
try {
|
||||||
MongoCollection<Document> c = database.getCollection(prefix + "users");
|
MongoCollection<Document> c = database.getCollection(prefix + "users");
|
||||||
|
|
||||||
try (MongoCursor<Document> cursor = c.find().iterator()) {
|
try (MongoCursor<Document> cursor = c.find().iterator()) {
|
||||||
while (cursor.hasNext()) {
|
while (cursor.hasNext()) {
|
||||||
Document d = cursor.next();
|
Document d = cursor.next();
|
||||||
@ -374,6 +335,7 @@ public class MongoDao extends AbstractDao {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
reportException(e);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return uuids;
|
return uuids;
|
||||||
@ -384,21 +346,17 @@ public class MongoDao extends AbstractDao {
|
|||||||
ImmutableList.Builder<HeldPermission<UUID>> held = ImmutableList.builder();
|
ImmutableList.Builder<HeldPermission<UUID>> held = ImmutableList.builder();
|
||||||
try {
|
try {
|
||||||
MongoCollection<Document> c = database.getCollection(prefix + "users");
|
MongoCollection<Document> c = database.getCollection(prefix + "users");
|
||||||
|
|
||||||
try (MongoCursor<Document> cursor = c.find().iterator()) {
|
try (MongoCursor<Document> cursor = c.find().iterator()) {
|
||||||
while (cursor.hasNext()) {
|
while (cursor.hasNext()) {
|
||||||
Document d = cursor.next();
|
Document d = cursor.next();
|
||||||
|
|
||||||
UUID holder = d.get("_id", UUID.class);
|
UUID holder = d.get("_id", UUID.class);
|
||||||
Map<String, Boolean> perms = revert((Map<String, Boolean>) d.get("perms"));
|
|
||||||
|
|
||||||
for (Map.Entry<String, Boolean> e : perms.entrySet()) {
|
Set<NodeModel> nodes = new HashSet<>(nodesFromDoc(d));
|
||||||
Node node = LegacyNodeFactory.fromLegacyString(e.getKey(), e.getValue());
|
for (NodeModel e : nodes) {
|
||||||
if (!node.getPermission().equalsIgnoreCase(permission)) {
|
if (!e.getPermission().equalsIgnoreCase(permission)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
held.add(NodeHeldPermission.of(holder, e));
|
||||||
held.add(NodeHeldPermission.of(holder, node));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -415,17 +373,13 @@ public class MongoDao extends AbstractDao {
|
|||||||
group.getIoLock().lock();
|
group.getIoLock().lock();
|
||||||
try {
|
try {
|
||||||
MongoCollection<Document> c = database.getCollection(prefix + "groups");
|
MongoCollection<Document> c = database.getCollection(prefix + "groups");
|
||||||
|
|
||||||
try (MongoCursor<Document> cursor = c.find(new Document("_id", group.getName())).iterator()) {
|
try (MongoCursor<Document> cursor = c.find(new Document("_id", group.getName())).iterator()) {
|
||||||
if (cursor.hasNext()) {
|
if (cursor.hasNext()) {
|
||||||
// Group exists, let's load.
|
|
||||||
Document d = cursor.next();
|
Document d = cursor.next();
|
||||||
group.setEnduringNodes(revert((Map<String, Boolean>) d.get("perms")).entrySet().stream()
|
Set<Node> nodes = nodesFromDoc(d).stream().map(NodeModel::toNode).collect(Collectors.toSet());
|
||||||
.map(e -> LegacyNodeFactory.fromLegacyString(e.getKey(), e.getValue()))
|
group.setEnduringNodes(nodes);
|
||||||
.collect(Collectors.toSet())
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
c.insertOne(fromGroup(group));
|
c.insertOne(groupToDoc(group));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -443,17 +397,14 @@ public class MongoDao extends AbstractDao {
|
|||||||
group.getIoLock().lock();
|
group.getIoLock().lock();
|
||||||
try {
|
try {
|
||||||
MongoCollection<Document> c = database.getCollection(prefix + "groups");
|
MongoCollection<Document> c = database.getCollection(prefix + "groups");
|
||||||
|
|
||||||
try (MongoCursor<Document> cursor = c.find(new Document("_id", group.getName())).iterator()) {
|
try (MongoCursor<Document> cursor = c.find(new Document("_id", group.getName())).iterator()) {
|
||||||
if (!cursor.hasNext()) {
|
if (!cursor.hasNext()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Document d = cursor.next();
|
Document d = cursor.next();
|
||||||
group.setEnduringNodes(revert((Map<String, Boolean>) d.get("perms")).entrySet().stream()
|
Set<Node> nodes = nodesFromDoc(d).stream().map(NodeModel::toNode).collect(Collectors.toSet());
|
||||||
.map(e -> LegacyNodeFactory.fromLegacyString(e.getKey(), e.getValue()))
|
group.setEnduringNodes(nodes);
|
||||||
.collect(Collectors.toSet())
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return reportException(e);
|
return reportException(e);
|
||||||
@ -469,11 +420,9 @@ public class MongoDao extends AbstractDao {
|
|||||||
List<String> groups = new ArrayList<>();
|
List<String> groups = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
MongoCollection<Document> c = database.getCollection(prefix + "groups");
|
MongoCollection<Document> c = database.getCollection(prefix + "groups");
|
||||||
|
|
||||||
try (MongoCursor<Document> cursor = c.find().iterator()) {
|
try (MongoCursor<Document> cursor = c.find().iterator()) {
|
||||||
while (cursor.hasNext()) {
|
while (cursor.hasNext()) {
|
||||||
String name = cursor.next().getString("_id");
|
String name = cursor.next().getString("_id");
|
||||||
loadGroup(name);
|
|
||||||
groups.add(name);
|
groups.add(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -482,6 +431,8 @@ public class MongoDao extends AbstractDao {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
groups.forEach(this::loadGroup);
|
||||||
|
|
||||||
GroupManager gm = plugin.getGroupManager();
|
GroupManager gm = plugin.getGroupManager();
|
||||||
gm.getAll().values().stream()
|
gm.getAll().values().stream()
|
||||||
.filter(g -> !groups.contains(g.getName()))
|
.filter(g -> !groups.contains(g.getName()))
|
||||||
@ -494,7 +445,7 @@ public class MongoDao extends AbstractDao {
|
|||||||
group.getIoLock().lock();
|
group.getIoLock().lock();
|
||||||
try {
|
try {
|
||||||
MongoCollection<Document> c = database.getCollection(prefix + "groups");
|
MongoCollection<Document> c = database.getCollection(prefix + "groups");
|
||||||
return c.replaceOne(new Document("_id", group.getName()), fromGroup(group)).wasAcknowledged();
|
return c.replaceOne(new Document("_id", group.getName()), groupToDoc(group), new UpdateOptions().upsert(true)).wasAcknowledged();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return reportException(e);
|
return reportException(e);
|
||||||
} finally {
|
} finally {
|
||||||
@ -507,17 +458,12 @@ public class MongoDao extends AbstractDao {
|
|||||||
group.getIoLock().lock();
|
group.getIoLock().lock();
|
||||||
try {
|
try {
|
||||||
MongoCollection<Document> c = database.getCollection(prefix + "groups");
|
MongoCollection<Document> c = database.getCollection(prefix + "groups");
|
||||||
if (!c.deleteOne(new Document("_id", group.getName())).wasAcknowledged()) {
|
return c.deleteOne(new Document("_id", group.getName())).wasAcknowledged();
|
||||||
throw new RuntimeException();
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return reportException(e);
|
return reportException(e);
|
||||||
} finally {
|
} finally {
|
||||||
group.getIoLock().unlock();
|
group.getIoLock().unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin.getGroupManager().unload(group);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -525,21 +471,17 @@ public class MongoDao extends AbstractDao {
|
|||||||
ImmutableList.Builder<HeldPermission<String>> held = ImmutableList.builder();
|
ImmutableList.Builder<HeldPermission<String>> held = ImmutableList.builder();
|
||||||
try {
|
try {
|
||||||
MongoCollection<Document> c = database.getCollection(prefix + "groups");
|
MongoCollection<Document> c = database.getCollection(prefix + "groups");
|
||||||
|
|
||||||
try (MongoCursor<Document> cursor = c.find().iterator()) {
|
try (MongoCursor<Document> cursor = c.find().iterator()) {
|
||||||
while (cursor.hasNext()) {
|
while (cursor.hasNext()) {
|
||||||
Document d = cursor.next();
|
Document d = cursor.next();
|
||||||
|
|
||||||
String holder = d.getString("_id");
|
String holder = d.getString("_id");
|
||||||
Map<String, Boolean> perms = revert((Map<String, Boolean>) d.get("perms"));
|
Set<NodeModel> nodes = new HashSet<>(nodesFromDoc(d));
|
||||||
|
for (NodeModel e : nodes) {
|
||||||
for (Map.Entry<String, Boolean> e : perms.entrySet()) {
|
if (!e.getPermission().equalsIgnoreCase(permission)) {
|
||||||
Node node = LegacyNodeFactory.fromLegacyString(e.getKey(), e.getValue());
|
|
||||||
if (!node.getPermission().equalsIgnoreCase(permission)) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
held.add(NodeHeldPermission.of(holder, e));
|
||||||
held.add(NodeHeldPermission.of(holder, node));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -556,12 +498,12 @@ public class MongoDao extends AbstractDao {
|
|||||||
track.getIoLock().lock();
|
track.getIoLock().lock();
|
||||||
try {
|
try {
|
||||||
MongoCollection<Document> c = database.getCollection(prefix + "tracks");
|
MongoCollection<Document> c = database.getCollection(prefix + "tracks");
|
||||||
|
|
||||||
try (MongoCursor<Document> cursor = c.find(new Document("_id", track.getName())).iterator()) {
|
try (MongoCursor<Document> cursor = c.find(new Document("_id", track.getName())).iterator()) {
|
||||||
if (!cursor.hasNext()) {
|
if (!cursor.hasNext()) {
|
||||||
c.insertOne(fromTrack(track));
|
c.insertOne(trackToDoc(track));
|
||||||
} else {
|
} else {
|
||||||
Document d = cursor.next();
|
Document d = cursor.next();
|
||||||
|
//noinspection unchecked
|
||||||
track.setGroups((List<String>) d.get("groups"));
|
track.setGroups((List<String>) d.get("groups"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -579,10 +521,10 @@ public class MongoDao extends AbstractDao {
|
|||||||
track.getIoLock().lock();
|
track.getIoLock().lock();
|
||||||
try {
|
try {
|
||||||
MongoCollection<Document> c = database.getCollection(prefix + "tracks");
|
MongoCollection<Document> c = database.getCollection(prefix + "tracks");
|
||||||
|
|
||||||
try (MongoCursor<Document> cursor = c.find(new Document("_id", track.getName())).iterator()) {
|
try (MongoCursor<Document> cursor = c.find(new Document("_id", track.getName())).iterator()) {
|
||||||
if (cursor.hasNext()) {
|
if (cursor.hasNext()) {
|
||||||
Document d = cursor.next();
|
Document d = cursor.next();
|
||||||
|
//noinspection unchecked
|
||||||
track.setGroups((List<String>) d.get("groups"));
|
track.setGroups((List<String>) d.get("groups"));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -600,11 +542,9 @@ public class MongoDao extends AbstractDao {
|
|||||||
List<String> tracks = new ArrayList<>();
|
List<String> tracks = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
MongoCollection<Document> c = database.getCollection(prefix + "tracks");
|
MongoCollection<Document> c = database.getCollection(prefix + "tracks");
|
||||||
|
|
||||||
try (MongoCursor<Document> cursor = c.find().iterator()) {
|
try (MongoCursor<Document> cursor = c.find().iterator()) {
|
||||||
while (cursor.hasNext()) {
|
while (cursor.hasNext()) {
|
||||||
String name = cursor.next().getString("_id");
|
String name = cursor.next().getString("_id");
|
||||||
loadTrack(name);
|
|
||||||
tracks.add(name);
|
tracks.add(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -613,6 +553,8 @@ public class MongoDao extends AbstractDao {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tracks.forEach(this::loadTrack);
|
||||||
|
|
||||||
TrackManager tm = plugin.getTrackManager();
|
TrackManager tm = plugin.getTrackManager();
|
||||||
tm.getAll().values().stream()
|
tm.getAll().values().stream()
|
||||||
.filter(t -> !tracks.contains(t.getName()))
|
.filter(t -> !tracks.contains(t.getName()))
|
||||||
@ -625,7 +567,7 @@ public class MongoDao extends AbstractDao {
|
|||||||
track.getIoLock().lock();
|
track.getIoLock().lock();
|
||||||
try {
|
try {
|
||||||
MongoCollection<Document> c = database.getCollection(prefix + "tracks");
|
MongoCollection<Document> c = database.getCollection(prefix + "tracks");
|
||||||
return c.replaceOne(new Document("_id", track.getName()), fromTrack(track)).wasAcknowledged();
|
return c.replaceOne(new Document("_id", track.getName()), trackToDoc(track)).wasAcknowledged();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return reportException(e);
|
return reportException(e);
|
||||||
} finally {
|
} finally {
|
||||||
@ -638,31 +580,19 @@ public class MongoDao extends AbstractDao {
|
|||||||
track.getIoLock().lock();
|
track.getIoLock().lock();
|
||||||
try {
|
try {
|
||||||
MongoCollection<Document> c = database.getCollection(prefix + "tracks");
|
MongoCollection<Document> c = database.getCollection(prefix + "tracks");
|
||||||
if (!c.deleteOne(new Document("_id", track.getName())).wasAcknowledged()) {
|
return c.deleteOne(new Document("_id", track.getName())).wasAcknowledged();
|
||||||
throw new RuntimeException();
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return reportException(e);
|
return reportException(e);
|
||||||
} finally {
|
} finally {
|
||||||
track.getIoLock().unlock();
|
track.getIoLock().unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin.getTrackManager().unload(track);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean saveUUIDData(UUID uuid, String username) {
|
public boolean saveUUIDData(UUID uuid, String username) {
|
||||||
try {
|
try {
|
||||||
MongoCollection<Document> c = database.getCollection(prefix + "uuid");
|
MongoCollection<Document> c = database.getCollection(prefix + "uuid");
|
||||||
|
c.replaceOne(new Document("_id", uuid), new Document("_id", uuid).append("name", username.toLowerCase()), new UpdateOptions().upsert(true));
|
||||||
try (MongoCursor<Document> cursor = c.find(new Document("_id", uuid)).iterator()) {
|
|
||||||
if (cursor.hasNext()) {
|
|
||||||
c.replaceOne(new Document("_id", uuid), new Document("_id", uuid).append("name", username.toLowerCase()));
|
|
||||||
} else {
|
|
||||||
c.insertOne(new Document("_id", uuid).append("name", username.toLowerCase()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return reportException(e);
|
return reportException(e);
|
||||||
}
|
}
|
||||||
@ -673,7 +603,6 @@ public class MongoDao extends AbstractDao {
|
|||||||
public UUID getUUID(String username) {
|
public UUID getUUID(String username) {
|
||||||
try {
|
try {
|
||||||
MongoCollection<Document> c = database.getCollection(prefix + "uuid");
|
MongoCollection<Document> c = database.getCollection(prefix + "uuid");
|
||||||
|
|
||||||
try (MongoCursor<Document> cursor = c.find(new Document("name", username.toLowerCase())).iterator()) {
|
try (MongoCursor<Document> cursor = c.find(new Document("name", username.toLowerCase())).iterator()) {
|
||||||
if (cursor.hasNext()) {
|
if (cursor.hasNext()) {
|
||||||
return cursor.next().get("_id", UUID.class);
|
return cursor.next().get("_id", UUID.class);
|
||||||
@ -690,7 +619,6 @@ public class MongoDao extends AbstractDao {
|
|||||||
public String getName(UUID uuid) {
|
public String getName(UUID uuid) {
|
||||||
try {
|
try {
|
||||||
MongoCollection<Document> c = database.getCollection(prefix + "uuid");
|
MongoCollection<Document> c = database.getCollection(prefix + "uuid");
|
||||||
|
|
||||||
try (MongoCursor<Document> cursor = c.find(new Document("_id", uuid)).iterator()) {
|
try (MongoCursor<Document> cursor = c.find(new Document("_id", uuid)).iterator()) {
|
||||||
if (cursor.hasNext()) {
|
if (cursor.hasNext()) {
|
||||||
return cursor.next().get("name", String.class);
|
return cursor.next().get("name", String.class);
|
||||||
@ -703,59 +631,126 @@ public class MongoDao extends AbstractDao {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* MongoDB does not allow '.' or '$' in key names.
|
private static Document userToDoc(User user) {
|
||||||
See: https://docs.mongodb.com/manual/reference/limits/#Restrictions-on-Field-Names
|
List<Document> nodes = user.getEnduringNodes().values().stream()
|
||||||
The following two methods convert the node maps so they can be stored. */
|
.map(NodeModel::fromNode)
|
||||||
|
.map(MongoDao::nodeToDoc)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
private static final Function<String, String> CONVERT_STRING = s -> s.replace(".", "[**DOT**]").replace("$", "[**DOLLAR**]");
|
return new Document("_id", user.getUuid())
|
||||||
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) {
|
|
||||||
return map.entrySet().stream()
|
|
||||||
.collect(Collectors.toMap(e -> CONVERT_STRING.apply(e.getKey()), Map.Entry::getValue));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static <V> Map<String, V> revert(Map<String, V> map) {
|
|
||||||
return map.entrySet().stream()
|
|
||||||
.collect(Collectors.toMap(e -> REVERT_STRING.apply(e.getKey()), Map.Entry::getValue));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Document fromUser(User user) {
|
|
||||||
Document main = new Document("_id", user.getUuid())
|
|
||||||
.append("name", user.getName().orElse("null"))
|
.append("name", user.getName().orElse("null"))
|
||||||
.append("primaryGroup", user.getPrimaryGroup().getStoredValue().orElse("default"));
|
.append("primaryGroup", user.getPrimaryGroup().getStoredValue().orElse("default"))
|
||||||
|
.append("permissions", nodes);
|
||||||
Document perms = new Document();
|
|
||||||
for (Map.Entry<String, Boolean> e : convert(exportToLegacy(user.getEnduringNodes().values())).entrySet()) {
|
|
||||||
perms.append(e.getKey(), e.getValue());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
main.append("perms", perms);
|
private static List<NodeModel> nodesFromDoc(Document document) {
|
||||||
return main;
|
List<NodeModel> nodes = new ArrayList<>();
|
||||||
|
|
||||||
|
// legacy
|
||||||
|
if (document.containsKey("perms") && document.get("perms") instanceof Map) {
|
||||||
|
//noinspection unchecked
|
||||||
|
Map<String, Boolean> permsMap = (Map<String, Boolean>) document.get("perms");
|
||||||
|
for (Map.Entry<String, Boolean> e : permsMap.entrySet()) {
|
||||||
|
// legacy permission key deserialisation
|
||||||
|
String permission = e.getKey().replace("[**DOT**]", ".").replace("[**DOLLAR**]", "$");
|
||||||
|
nodes.add(NodeModel.fromNode(LegacyNodeFactory.fromLegacyString(permission, e.getValue())));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Document fromGroup(Group group) {
|
// new format
|
||||||
Document main = new Document("_id", group.getName());
|
if (document.containsKey("permissions") && document.get("permissions") instanceof List) {
|
||||||
|
//noinspection unchecked
|
||||||
Document perms = new Document();
|
List<Document> permsList = (List<Document>) document.get("permissions");
|
||||||
for (Map.Entry<String, Boolean> e : convert(exportToLegacy(group.getEnduringNodes().values())).entrySet()) {
|
for (Document d : permsList) {
|
||||||
perms.append(e.getKey(), e.getValue());
|
nodes.add(nodeFromDoc(d));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
main.append("perms", perms);
|
return nodes;
|
||||||
return main;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Document fromTrack(Track track) {
|
private static Document groupToDoc(Group group) {
|
||||||
|
List<Document> nodes = group.getEnduringNodes().values().stream()
|
||||||
|
.map(NodeModel::fromNode)
|
||||||
|
.map(MongoDao::nodeToDoc)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
return new Document("_id", group.getName()).append("permissions", nodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Document trackToDoc(Track track) {
|
||||||
return new Document("_id", track.getName()).append("groups", track.getGroups());
|
return new Document("_id", track.getName()).append("groups", track.getGroups());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Map<String, Boolean> exportToLegacy(Iterable<Node> nodes) {
|
private static Document nodeToDoc(NodeModel node) {
|
||||||
Map<String, Boolean> m = new HashMap<>();
|
Document document = new Document();
|
||||||
for (Node node : nodes) {
|
|
||||||
//noinspection deprecation
|
document.append("permission", node.getPermission());
|
||||||
m.put(LegacyNodeFactory.toSerializedNode(node), node.getValuePrimitive());
|
document.append("value", node.getValue());
|
||||||
|
|
||||||
|
if (!node.getServer().equals("global")) {
|
||||||
|
document.append("server", node.getServer());
|
||||||
}
|
}
|
||||||
return m;
|
|
||||||
|
if (!node.getWorld().equals("global")) {
|
||||||
|
document.append("world", node.getWorld());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (node.getExpiry() != 0L) {
|
||||||
|
document.append("expiry", node.getExpiry());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!node.getContexts().isEmpty()) {
|
||||||
|
document.append("context", contextSetToDocs(node.getContexts()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return document;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static NodeModel nodeFromDoc(Document document) {
|
||||||
|
String permission = document.getString("permission");
|
||||||
|
boolean value = true;
|
||||||
|
String server = "global";
|
||||||
|
String world = "global";
|
||||||
|
long expiry = 0L;
|
||||||
|
ImmutableContextSet context = ImmutableContextSet.empty();
|
||||||
|
|
||||||
|
if (document.containsKey("value")) {
|
||||||
|
value = document.getBoolean("value");
|
||||||
|
}
|
||||||
|
if (document.containsKey("server")) {
|
||||||
|
server = document.getString("server");
|
||||||
|
}
|
||||||
|
if (document.containsKey("world")) {
|
||||||
|
world = document.getString("world");
|
||||||
|
}
|
||||||
|
if (document.containsKey("expiry")) {
|
||||||
|
expiry = document.getLong("expiry");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (document.containsKey("context") && document.get("context") instanceof List) {
|
||||||
|
//noinspection unchecked
|
||||||
|
List<Document> contexts = (List<Document>) document.get("context");
|
||||||
|
context = docsToContextSet(contexts).makeImmutable();
|
||||||
|
}
|
||||||
|
|
||||||
|
return NodeModel.of(permission, value, server, world, expiry, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<Document> contextSetToDocs(ContextSet contextSet) {
|
||||||
|
List<Document> contexts = new ArrayList<>();
|
||||||
|
for (Map.Entry<String, String> e : contextSet.toSet()) {
|
||||||
|
contexts.add(new Document().append("key", e.getKey()).append("value", e.getValue()));
|
||||||
|
}
|
||||||
|
return contexts;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static MutableContextSet docsToContextSet(List<Document> documents) {
|
||||||
|
MutableContextSet map = MutableContextSet.create();
|
||||||
|
for (Document doc : documents) {
|
||||||
|
map.add(doc.getString("key"), doc.getString("value"));
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user