diff --git a/common/src/main/java/me/lucko/luckperms/common/storage/implementation/mongodb/MongoStorage.java b/common/src/main/java/me/lucko/luckperms/common/storage/implementation/mongodb/MongoStorage.java index 364b92569..b07afe06a 100644 --- a/common/src/main/java/me/lucko/luckperms/common/storage/implementation/mongodb/MongoStorage.java +++ b/common/src/main/java/me/lucko/luckperms/common/storage/implementation/mongodb/MongoStorage.java @@ -36,6 +36,7 @@ import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoCursor; import com.mongodb.client.MongoDatabase; import com.mongodb.client.model.Filters; +import com.mongodb.client.model.Indexes; import com.mongodb.client.model.ReplaceOptions; import com.mongodb.client.model.Sorts; import com.mongodb.client.model.UpdateOptions; @@ -149,6 +150,7 @@ public class MongoStorage implements StorageImplementation { } this.database = this.mongoClient.getDatabase(this.configuration.getDatabase()); + ensureIndexes(); } @Override @@ -751,4 +753,10 @@ public class MongoStorage implements StorageImplementation { } } + private void ensureIndexes() { + this.database.getCollection(this.prefix + "uuid").createIndex(Indexes.ascending("name")); + this.database.getCollection(this.prefix + "users").createIndex(Indexes.ascending("permissions.key")); + this.database.getCollection(this.prefix + "groups").createIndex(Indexes.ascending("permissions.key")); + } + } diff --git a/common/src/test/java/me/lucko/luckperms/common/storage/MongoStorageTest.java b/common/src/test/java/me/lucko/luckperms/common/storage/MongoStorageTest.java index cc28698da..56e0b90fe 100644 --- a/common/src/test/java/me/lucko/luckperms/common/storage/MongoStorageTest.java +++ b/common/src/test/java/me/lucko/luckperms/common/storage/MongoStorageTest.java @@ -25,37 +25,116 @@ package me.lucko.luckperms.common.storage; +import com.mongodb.MongoClient; +import com.mongodb.ServerAddress; +import com.mongodb.client.MongoDatabase; import me.lucko.luckperms.common.plugin.LuckPermsPlugin; import me.lucko.luckperms.common.storage.implementation.StorageImplementation; import me.lucko.luckperms.common.storage.implementation.mongodb.MongoStorage; import me.lucko.luckperms.common.storage.misc.StorageCredentials; +import org.bson.Document; import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; import org.testcontainers.containers.GenericContainer; import org.testcontainers.utility.DockerImageName; +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + @Tag("docker") public class MongoStorageTest extends AbstractStorageTest { + private static final String DATABASE = "minecraft"; + private static final String PREFIX = "luckperms_"; private final GenericContainer container = new GenericContainer<>(DockerImageName.parse("mongo")) .withExposedPorts(27017); + private String host; + private int port; @Override protected StorageImplementation makeStorage(LuckPermsPlugin plugin) throws Exception { this.container.start(); - String host = this.container.getHost(); - Integer port = this.container.getFirstMappedPort(); + this.host = this.container.getHost(); + this.port = this.container.getFirstMappedPort(); StorageCredentials credentials = new StorageCredentials( - host + ":" + port, - "minecraft", + this.host + ":" + this.port, + DATABASE, "", "" ); - return new MongoStorage(plugin, credentials, "", ""); + return new MongoStorage(plugin, credentials, PREFIX, ""); } @Override protected void cleanupResources() { this.container.stop(); } + + @Test + public void testIndexesAreCreatedAndInitIsIdempotent() throws Exception { + this.storage.shutdown(); + this.storage.init(); + + try (MongoClient client = new MongoClient(new ServerAddress(this.host, this.port))) { + MongoDatabase database = client.getDatabase(DATABASE); + + assertIndexCreatedOnce( + database, + PREFIX + "uuid", + "_id_", + new Document("_id", 1) + ); + + assertIndexCreatedOnce( + database, + PREFIX + "uuid", + "name_1", + new Document("name", 1) + ); + + assertIndexCreatedOnce( + database, + PREFIX + "users", + "permissions.key_1", + new Document("permissions.key", 1) + ); + + assertIndexCreatedOnce( + database, + PREFIX + "groups", + "permissions.key_1", + new Document("permissions.key", 1) + ); + } + } + + private static void assertIndexCreatedOnce( + MongoDatabase database, + String collectionName, + String indexName, + Document expectedKey) { + List collectionIndexes = database.getCollection(collectionName).listIndexes().into(new ArrayList<>()); + Document collectionIndex = collectionIndexes.stream() + .filter(index -> indexName.equals(index.getString("name"))) + .findFirst().orElse(null); + + assertNotNull(collectionIndex); + + assertEquals( + expectedKey, + collectionIndex.get("key", Document.class) + ); + + // Ensure index has not been duplicated. + assertEquals( + 1L, + collectionIndexes.stream() + .filter(index -> indexName.equals(index.getString("name"))) + .count() + ); + } }