Add support for MongoDB and H2 database formats
This commit is contained in:
@@ -96,6 +96,11 @@ public interface LuckPermsPlugin {
|
||||
*/
|
||||
File getMainDir();
|
||||
|
||||
/**
|
||||
* @return the platforms data folder
|
||||
*/
|
||||
File getDataFolder();
|
||||
|
||||
/**
|
||||
* @return the importer instance for the platform
|
||||
*/
|
||||
@@ -126,6 +131,12 @@ public interface LuckPermsPlugin {
|
||||
*/
|
||||
List<Sender> getSenders();
|
||||
|
||||
/**
|
||||
* Gets the console sender of the instance
|
||||
* @return a the console sender of the instance
|
||||
*/
|
||||
Sender getConsoleSender();
|
||||
|
||||
/**
|
||||
* Gets all possible permission nodes, used for resolving wildcards
|
||||
* @return a {@link List} of permission nodes
|
||||
|
||||
+7
@@ -24,6 +24,7 @@ package me.lucko.luckperms.api.implementation.internal;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import me.lucko.luckperms.api.LPConfiguration;
|
||||
import me.lucko.luckperms.api.data.DatastoreConfiguration;
|
||||
import me.lucko.luckperms.api.data.MySQLConfiguration;
|
||||
|
||||
/**
|
||||
@@ -78,8 +79,14 @@ public class LPConfigurationLink implements LPConfiguration {
|
||||
return master.getApplyShorthand();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public MySQLConfiguration getDatabaseValues() {
|
||||
return getDatastoreConfig();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatastoreConfiguration getDatastoreConfig() {
|
||||
return master.getDatabaseValues();
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.constants.Patterns;
|
||||
import me.lucko.luckperms.storage.MySQLConfiguration;
|
||||
import me.lucko.luckperms.storage.DatastoreConfiguration;
|
||||
|
||||
public abstract class LPConfiguration<T extends LuckPermsPlugin> {
|
||||
|
||||
@@ -70,7 +70,7 @@ public abstract class LPConfiguration<T extends LuckPermsPlugin> {
|
||||
}
|
||||
|
||||
public int getSyncTime() {
|
||||
return getInt("sql.sync-minutes", 3);
|
||||
return getInt("data.sync-minutes", 3);
|
||||
}
|
||||
|
||||
public String getDefaultGroupNode() {
|
||||
@@ -101,12 +101,12 @@ public abstract class LPConfiguration<T extends LuckPermsPlugin> {
|
||||
return getBoolean("apply-shorthand", true);
|
||||
}
|
||||
|
||||
public MySQLConfiguration getDatabaseValues() {
|
||||
return new MySQLConfiguration(
|
||||
getString("sql.address", null),
|
||||
getString("sql.database", null),
|
||||
getString("sql.username", null),
|
||||
getString("sql.password", null)
|
||||
public DatastoreConfiguration getDatabaseValues() {
|
||||
return new DatastoreConfiguration(
|
||||
getString("data.address", null),
|
||||
getString("data.database", null),
|
||||
getString("data.username", null),
|
||||
getString("data.password", null)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,9 @@ import me.lucko.luckperms.groups.Group;
|
||||
import me.lucko.luckperms.tracks.Track;
|
||||
import me.lucko.luckperms.users.User;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class LogEntry extends me.lucko.luckperms.api.LogEntry {
|
||||
public static LogEntryBuilder build() {
|
||||
return new LogEntryBuilder();
|
||||
@@ -45,8 +48,12 @@ public class LogEntry extends me.lucko.luckperms.api.LogEntry {
|
||||
|
||||
final String msg = super.getFormatted();
|
||||
|
||||
plugin.getSenders().stream()
|
||||
List<Sender> senders = plugin.getSenders().stream()
|
||||
.filter(Permission.LOG_NOTIFY::isAuthorized)
|
||||
.collect(Collectors.toList());
|
||||
senders.add(plugin.getConsoleSender());
|
||||
|
||||
senders.stream()
|
||||
.filter(s -> !plugin.getIgnoringLogs().contains(s.getUuid()))
|
||||
.forEach(s -> Message.LOG.send(s, msg));
|
||||
}
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public class MySQLConfiguration implements me.lucko.luckperms.api.data.MySQLConfiguration {
|
||||
public class DatastoreConfiguration implements me.lucko.luckperms.api.data.DatastoreConfiguration {
|
||||
|
||||
private final String address;
|
||||
private final String database;
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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.storage;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.storage.methods.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Set;
|
||||
|
||||
@UtilityClass
|
||||
public class StorageFactory {
|
||||
private static final Set<String> TYPES = ImmutableSet.of("flatfile", "mongodb", "mysql", "sqlite", "h2");
|
||||
|
||||
public static Datastore getDatastore(LuckPermsPlugin plugin, String defaultMethod) {
|
||||
Datastore datastore;
|
||||
|
||||
plugin.getLog().info("Detecting storage method...");
|
||||
String storageMethod = plugin.getConfiguration().getStorageMethod().toLowerCase();
|
||||
|
||||
if (!TYPES.contains(storageMethod)) {
|
||||
plugin.getLog().severe("Storage method '" + storageMethod + "' not recognised. Using the default instead.");
|
||||
storageMethod = defaultMethod;
|
||||
}
|
||||
|
||||
switch (storageMethod) {
|
||||
case "mysql":
|
||||
plugin.getLog().info("Using MySQL as storage method.");
|
||||
datastore = new MySQLDatastore(plugin, plugin.getConfiguration().getDatabaseValues());
|
||||
break;
|
||||
case "sqlite":
|
||||
plugin.getLog().info("Using SQLite as storage method.");
|
||||
datastore = new SQLiteDatastore(plugin, new File(plugin.getDataFolder(), "luckperms.sqlite"));
|
||||
break;
|
||||
case "h2":
|
||||
plugin.getLog().info("Using H2 as storage method.");
|
||||
datastore = new H2Datastore(plugin, new File(plugin.getDataFolder(), "luckperms.db"));
|
||||
break;
|
||||
case "mongodb":
|
||||
plugin.getLog().info("Using MongoDB as storage method.");
|
||||
datastore = new MongoDBDatastore(plugin, plugin.getConfiguration().getDatabaseValues());
|
||||
break;
|
||||
default:
|
||||
plugin.getLog().info("Using Flatfile (JSON) as storage method.");
|
||||
datastore = new FlatfileDatastore(plugin, plugin.getDataFolder());
|
||||
break;
|
||||
}
|
||||
|
||||
plugin.getLog().info("Initialising datastore...");
|
||||
datastore.init();
|
||||
return datastore;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* 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.storage.methods;
|
||||
|
||||
import lombok.Cleanup;
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.*;
|
||||
|
||||
public class H2Datastore extends SQLDatastore {
|
||||
|
||||
private static final String CREATETABLE_UUID = "CREATE TABLE IF NOT EXISTS `lp_uuid` (`name` VARCHAR(16) NOT NULL, `uuid` VARCHAR(36) NOT NULL, PRIMARY KEY (`name`)) DEFAULT CHARSET=utf8;";
|
||||
private static final String CREATETABLE_USERS = "CREATE TABLE IF NOT EXISTS `lp_users` (`uuid` VARCHAR(36) NOT NULL, `name` VARCHAR(16) NOT NULL, `primary_group` VARCHAR(36) NOT NULL, `perms` TEXT NOT NULL, PRIMARY KEY (`uuid`)) DEFAULT CHARSET=utf8;";
|
||||
private static final String CREATETABLE_GROUPS = "CREATE TABLE IF NOT EXISTS `lp_groups` (`name` VARCHAR(36) NOT NULL, `perms` TEXT NULL, PRIMARY KEY (`name`)) DEFAULT CHARSET=utf8;";
|
||||
private static final String CREATETABLE_TRACKS = "CREATE TABLE IF NOT EXISTS `lp_tracks` (`name` VARCHAR(36) NOT NULL, `groups` TEXT NULL, PRIMARY KEY (`name`)) DEFAULT CHARSET=utf8;";
|
||||
private static final String CREATETABLE_ACTION = "CREATE TABLE IF NOT EXISTS `lp_actions` (`id` INT AUTO_INCREMENT NOT NULL, `time` BIGINT NOT NULL, `actor_uuid` VARCHAR(36) NOT NULL, `actor_name` VARCHAR(16) NOT NULL, `type` CHAR(1) NOT NULL, `acted_uuid` VARCHAR(36) NOT NULL, `acted_name` VARCHAR(36) NOT NULL, `action` VARCHAR(256) NOT NULL, PRIMARY KEY (`id`)) DEFAULT CHARSET=utf8;";
|
||||
|
||||
private final File file;
|
||||
private Connection connection = null;
|
||||
|
||||
public H2Datastore(LuckPermsPlugin plugin, File file) {
|
||||
super(plugin, "H2");
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
if (!setupTables(CREATETABLE_UUID, CREATETABLE_USERS, CREATETABLE_GROUPS, CREATETABLE_TRACKS, CREATETABLE_ACTION)) {
|
||||
plugin.getLog().severe("Error occurred whilst initialising the database.");
|
||||
shutdown();
|
||||
} else {
|
||||
setAcceptingLogins(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean runQuery(QueryPS queryPS) {
|
||||
boolean success = false;
|
||||
try {
|
||||
Connection connection = getConnection();
|
||||
if (connection == null || connection.isClosed()) {
|
||||
throw new IllegalStateException("SQL connection is null");
|
||||
}
|
||||
|
||||
@Cleanup PreparedStatement preparedStatement = connection.prepareStatement(queryPS.getQuery());
|
||||
queryPS.onRun(preparedStatement);
|
||||
preparedStatement.execute();
|
||||
success = true;
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean runQuery(QueryRS queryRS) {
|
||||
boolean success = false;
|
||||
try {
|
||||
Connection connection = getConnection();
|
||||
if (connection == null || connection.isClosed()) {
|
||||
throw new IllegalStateException("SQL connection is null");
|
||||
}
|
||||
|
||||
@Cleanup PreparedStatement preparedStatement = connection.prepareStatement(queryRS.getQuery());
|
||||
queryRS.onRun(preparedStatement);
|
||||
preparedStatement.execute();
|
||||
|
||||
@Cleanup ResultSet resultSet = preparedStatement.executeQuery();
|
||||
success = queryRS.onResult(resultSet);
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
try {
|
||||
if (connection != null && !connection.isClosed()) {
|
||||
connection.close();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
Connection getConnection() throws SQLException {
|
||||
if (connection == null || connection.isClosed()) {
|
||||
try {
|
||||
Class.forName("org.h2.Driver");
|
||||
} catch (ClassNotFoundException ignored) {}
|
||||
|
||||
connection = DriverManager.getConnection("jdbc:h2:" + file.getAbsolutePath());
|
||||
}
|
||||
|
||||
return connection;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,453 @@
|
||||
/*
|
||||
* 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.storage.methods;
|
||||
|
||||
import com.mongodb.MongoClient;
|
||||
import com.mongodb.MongoCredential;
|
||||
import com.mongodb.ServerAddress;
|
||||
import com.mongodb.client.MongoCollection;
|
||||
import com.mongodb.client.MongoCursor;
|
||||
import com.mongodb.client.MongoDatabase;
|
||||
import com.mongodb.client.model.InsertOneOptions;
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.api.LogEntry;
|
||||
import me.lucko.luckperms.data.Log;
|
||||
import me.lucko.luckperms.groups.Group;
|
||||
import me.lucko.luckperms.groups.GroupManager;
|
||||
import me.lucko.luckperms.storage.Datastore;
|
||||
import me.lucko.luckperms.storage.DatastoreConfiguration;
|
||||
import me.lucko.luckperms.tracks.Track;
|
||||
import me.lucko.luckperms.tracks.TrackManager;
|
||||
import me.lucko.luckperms.users.User;
|
||||
import org.bson.Document;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public class MongoDBDatastore extends Datastore {
|
||||
|
||||
private final DatastoreConfiguration configuration;
|
||||
private MongoClient mongoClient;
|
||||
private MongoDatabase database;
|
||||
|
||||
public MongoDBDatastore(LuckPermsPlugin plugin, DatastoreConfiguration configuration) {
|
||||
super(plugin, "MongoDB");
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
MongoCredential credential = MongoCredential.createCredential(
|
||||
configuration.getUsername(),
|
||||
configuration.getDatabase(),
|
||||
configuration.getPassword().toCharArray()
|
||||
);
|
||||
|
||||
ServerAddress address = new ServerAddress(
|
||||
configuration.getAddress().split(":")[0],
|
||||
Integer.parseInt(configuration.getAddress().split(":")[1])
|
||||
);
|
||||
|
||||
mongoClient = new MongoClient(address, Collections.singletonList(credential));
|
||||
database = mongoClient.getDatabase(configuration.getDatabase());
|
||||
setAcceptingLogins(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
if (mongoClient != null) {
|
||||
mongoClient.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean logAction(LogEntry entry) {
|
||||
return call(() -> {
|
||||
MongoCollection<Document> c = database.getCollection("action");
|
||||
|
||||
Document doc = new Document()
|
||||
.append("timestamp", entry.getTimestamp())
|
||||
.append("actor", entry.getActor())
|
||||
.append("actorName", entry.getActorName())
|
||||
.append("type", Character.toString(entry.getType()))
|
||||
.append("actedName", entry.getActedName())
|
||||
.append("action", entry.getAction());
|
||||
|
||||
if (entry.getActed() != null) {
|
||||
doc.append("acted", entry.getActed());
|
||||
}
|
||||
|
||||
c.insertOne(doc, new InsertOneOptions());
|
||||
return true;
|
||||
}, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Log getLog() {
|
||||
return call(() -> {
|
||||
final Log.Builder log = Log.builder();
|
||||
MongoCollection<Document> c = database.getCollection("action");
|
||||
|
||||
try (MongoCursor<Document> cursor = c.find().iterator()) {
|
||||
while (cursor.hasNext()) {
|
||||
Document d = cursor.next();
|
||||
|
||||
UUID actedUuid = null;
|
||||
if (d.containsKey("acted")) {
|
||||
actedUuid = d.get("acted", UUID.class);
|
||||
}
|
||||
|
||||
LogEntry e = new LogEntry(
|
||||
d.getLong("timestamp"),
|
||||
d.get("actor", UUID.class),
|
||||
d.getString("actorName"),
|
||||
d.getString("type").toCharArray()[0],
|
||||
actedUuid,
|
||||
d.getString("actedName"),
|
||||
d.getString("action")
|
||||
);
|
||||
log.add(e);
|
||||
}
|
||||
}
|
||||
|
||||
return log.build();
|
||||
}, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadOrCreateUser(UUID uuid, String username) {
|
||||
User user = plugin.getUserManager().make(uuid, username);
|
||||
boolean success = call(() -> {
|
||||
MongoCollection<Document> c = database.getCollection("users");
|
||||
|
||||
try (MongoCursor<Document> cursor = c.find(new Document("_id", user.getUuid())).iterator()) {
|
||||
if (!cursor.hasNext()) {
|
||||
plugin.getUserManager().giveDefaults(user);
|
||||
c.insertOne(fromUser(user));
|
||||
} else {
|
||||
Document d = cursor.next();
|
||||
user.setPrimaryGroup(d.getString("primaryGroup"));
|
||||
user.setNodes(revert((Map<String, Boolean>) d.get("perms")));
|
||||
|
||||
if (!d.getString("name").equals(user.getName())) {
|
||||
c.replaceOne(new Document("_id", user.getUuid()), fromUser(user));
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}, false);
|
||||
|
||||
if (success) plugin.getUserManager().updateOrSet(user);
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadUser(UUID uuid) {
|
||||
User user = plugin.getUserManager().make(uuid);
|
||||
boolean success = call(() -> {
|
||||
MongoCollection<Document> c = database.getCollection("users");
|
||||
|
||||
try (MongoCursor<Document> cursor = c.find(new Document("_id", user.getUuid())).iterator()) {
|
||||
if (cursor.hasNext()) {
|
||||
Document d = cursor.next();
|
||||
user.setName(d.getString("name"));
|
||||
user.setPrimaryGroup(d.getString("primaryGroup"));
|
||||
user.setNodes(revert((Map<String, Boolean>) d.get("perms")));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}, false);
|
||||
|
||||
if (success) plugin.getUserManager().updateOrSet(user);
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveUser(User user) {
|
||||
return call(() -> {
|
||||
MongoCollection<Document> c = database.getCollection("users");
|
||||
c.replaceOne(new Document("_id", user.getUuid()), fromUser(user));
|
||||
return true;
|
||||
}, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createAndLoadGroup(String name) {
|
||||
Group group = plugin.getGroupManager().make(name);
|
||||
boolean success = call(() -> {
|
||||
MongoCollection<Document> c = database.getCollection("groups");
|
||||
|
||||
try (MongoCursor<Document> cursor = c.find(new Document("_id", group.getName())).iterator()) {
|
||||
if (!cursor.hasNext()) {
|
||||
c.insertOne(fromGroup(group));
|
||||
} else {
|
||||
Document d = cursor.next();
|
||||
group.setNodes(revert((Map<String, Boolean>) d.get("perms")));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}, false);
|
||||
|
||||
if (success) plugin.getGroupManager().updateOrSet(group);
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadGroup(String name) {
|
||||
Group group = plugin.getGroupManager().make(name);
|
||||
boolean success = call(() -> {
|
||||
MongoCollection<Document> c = database.getCollection("groups");
|
||||
|
||||
try (MongoCursor<Document> cursor = c.find(new Document("_id", group.getName())).iterator()) {
|
||||
if (cursor.hasNext()) {
|
||||
Document d = cursor.next();
|
||||
group.setNodes(revert((Map<String, Boolean>) d.get("perms")));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}, false);
|
||||
|
||||
if (success) plugin.getGroupManager().updateOrSet(group);
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadAllGroups() {
|
||||
List<Group> groups = new ArrayList<>();
|
||||
boolean success = call(() -> {
|
||||
MongoCollection<Document> c = database.getCollection("groups");
|
||||
|
||||
try (MongoCursor<Document> cursor = c.find().iterator()) {
|
||||
while (cursor.hasNext()) {
|
||||
Document d = cursor.next();
|
||||
Group group = plugin.getGroupManager().make(d.getString("_id"));
|
||||
group.setNodes(revert((Map<String, Boolean>) d.get("perms")));
|
||||
groups.add(group);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}, false);
|
||||
|
||||
if (success) {
|
||||
GroupManager gm = plugin.getGroupManager();
|
||||
gm.unloadAll();
|
||||
groups.forEach(gm::set);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveGroup(Group group) {
|
||||
return call(() -> {
|
||||
MongoCollection<Document> c = database.getCollection("groups");
|
||||
return c.replaceOne(new Document("_id", group.getName()), fromGroup(group)).wasAcknowledged();
|
||||
}, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteGroup(Group group) {
|
||||
boolean success = call(() -> {
|
||||
MongoCollection<Document> c = database.getCollection("groups");
|
||||
return c.deleteOne(new Document("_id", group.getName())).wasAcknowledged();
|
||||
}, false);
|
||||
|
||||
if (success) plugin.getGroupManager().unload(group);
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createAndLoadTrack(String name) {
|
||||
Track track = plugin.getTrackManager().make(name);
|
||||
boolean success = call(() -> {
|
||||
MongoCollection<Document> c = database.getCollection("tracks");
|
||||
|
||||
try (MongoCursor<Document> cursor = c.find(new Document("_id", track.getName())).iterator()) {
|
||||
if (!cursor.hasNext()) {
|
||||
c.insertOne(fromTrack(track));
|
||||
} else {
|
||||
Document d = cursor.next();
|
||||
track.setGroups((List<String>) d.get("groups"));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}, false);
|
||||
|
||||
if (success) plugin.getTrackManager().updateOrSet(track);
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadTrack(String name) {
|
||||
Track track = plugin.getTrackManager().make(name);
|
||||
boolean success = call(() -> {
|
||||
MongoCollection<Document> c = database.getCollection("tracks");
|
||||
|
||||
try (MongoCursor<Document> cursor = c.find(new Document("_id", track.getName())).iterator()) {
|
||||
if (cursor.hasNext()) {
|
||||
Document d = cursor.next();
|
||||
track.setGroups((List<String>) d.get("groups"));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}, false);
|
||||
|
||||
if (success) plugin.getTrackManager().updateOrSet(track);
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadAllTracks() {
|
||||
List<Track> tracks = new ArrayList<>();
|
||||
boolean success = call(() -> {
|
||||
MongoCollection<Document> c = database.getCollection("tracks");
|
||||
|
||||
try (MongoCursor<Document> cursor = c.find().iterator()) {
|
||||
while (cursor.hasNext()) {
|
||||
Document d = cursor.next();
|
||||
Track track = plugin.getTrackManager().make(d.getString("_id"));
|
||||
track.setGroups((List<String>) d.get("groups"));
|
||||
tracks.add(track);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}, false);
|
||||
|
||||
if (success) {
|
||||
TrackManager tm = plugin.getTrackManager();
|
||||
tm.unloadAll();
|
||||
tracks.forEach(tm::set);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveTrack(Track track) {
|
||||
return call(() -> {
|
||||
MongoCollection<Document> c = database.getCollection("tracks");
|
||||
return c.replaceOne(new Document("_id", track.getName()), fromTrack(track)).wasAcknowledged();
|
||||
}, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteTrack(Track track) {
|
||||
boolean success = call(() -> {
|
||||
MongoCollection<Document> c = database.getCollection("tracks");
|
||||
return c.deleteOne(new Document("_id", track.getName())).wasAcknowledged();
|
||||
}, false);
|
||||
|
||||
if (success) plugin.getTrackManager().unload(track);
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveUUIDData(String username, UUID uuid) {
|
||||
return call(() -> {
|
||||
MongoCollection<Document> c = database.getCollection("uuid");
|
||||
|
||||
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()));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID(String username) {
|
||||
return call(() -> {
|
||||
MongoCollection<Document> c = database.getCollection("uuid");
|
||||
|
||||
try (MongoCursor<Document> cursor = c.find(new Document("name", username.toLowerCase())).iterator()) {
|
||||
if (cursor.hasNext()) {
|
||||
return cursor.next().get("_id", UUID.class);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}, null);
|
||||
}
|
||||
|
||||
private static <T> T call(Callable<T> c, T def) {
|
||||
try {
|
||||
return c.call();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
/* MongoDB does not allow '.' or '$' in key 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. */
|
||||
private static <V> Map<String, V> convert(Map<String, V> map) {
|
||||
return map.entrySet().stream()
|
||||
.map(e -> new AbstractMap.SimpleEntry<>(e.getKey().replace(".", "[**DOT**]").replace("$", "[**DOLLAR**]"), e.getValue()))
|
||||
.collect(Collectors.toMap(AbstractMap.SimpleEntry::getKey, AbstractMap.SimpleEntry::getValue));
|
||||
}
|
||||
|
||||
private static <V> Map<String, V> revert(Map<String, V> map) {
|
||||
return map.entrySet().stream()
|
||||
.map(e -> new AbstractMap.SimpleEntry<>(e.getKey().replace("[**DOT**]", ".").replace("[**DOLLAR**]", "$"), e.getValue()))
|
||||
.collect(Collectors.toMap(AbstractMap.SimpleEntry::getKey, AbstractMap.SimpleEntry::getValue));
|
||||
}
|
||||
|
||||
private static Document fromUser(User user) {
|
||||
Document main = new Document("_id", user.getUuid())
|
||||
.append("name", user.getName())
|
||||
.append("primaryGroup", user.getPrimaryGroup());
|
||||
|
||||
Document perms = new Document();
|
||||
for (Map.Entry<String, Boolean> e : convert(user.getNodes()).entrySet()) {
|
||||
perms.append(e.getKey(), e.getValue());
|
||||
}
|
||||
|
||||
main.append("perms", perms);
|
||||
return main;
|
||||
}
|
||||
|
||||
private static Document fromGroup(Group group) {
|
||||
Document main = new Document("_id", group.getName());
|
||||
|
||||
Document perms = new Document();
|
||||
for (Map.Entry<String, Boolean> e : convert(group.getNodes()).entrySet()) {
|
||||
perms.append(e.getKey(), e.getValue());
|
||||
}
|
||||
|
||||
main.append("perms", perms);
|
||||
return main;
|
||||
}
|
||||
|
||||
private static Document fromTrack(Track track) {
|
||||
return new Document("_id", track.getName()).append("groups", track.getGroups());
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,7 @@ package me.lucko.luckperms.storage.methods;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
import lombok.Cleanup;
|
||||
import me.lucko.luckperms.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.storage.MySQLConfiguration;
|
||||
import me.lucko.luckperms.storage.DatastoreConfiguration;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
@@ -40,10 +40,10 @@ public class MySQLDatastore extends SQLDatastore {
|
||||
private static final String CREATETABLE_TRACKS = "CREATE TABLE IF NOT EXISTS `lp_tracks` (`name` VARCHAR(36) NOT NULL, `groups` TEXT NULL, PRIMARY KEY (`name`)) DEFAULT CHARSET=utf8;";
|
||||
private static final String CREATETABLE_ACTION = "CREATE TABLE IF NOT EXISTS `lp_actions` (`id` INT AUTO_INCREMENT NOT NULL, `time` BIGINT NOT NULL, `actor_uuid` VARCHAR(36) NOT NULL, `actor_name` VARCHAR(16) NOT NULL, `type` CHAR(1) NOT NULL, `acted_uuid` VARCHAR(36) NOT NULL, `acted_name` VARCHAR(36) NOT NULL, `action` VARCHAR(256) NOT NULL, PRIMARY KEY (`id`)) DEFAULT CHARSET=utf8;";
|
||||
|
||||
private final MySQLConfiguration configuration;
|
||||
private final DatastoreConfiguration configuration;
|
||||
private HikariDataSource hikari;
|
||||
|
||||
public MySQLDatastore(LuckPermsPlugin plugin, MySQLConfiguration configuration) {
|
||||
public MySQLDatastore(LuckPermsPlugin plugin, DatastoreConfiguration configuration) {
|
||||
super(plugin, "MySQL");
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ abstract class SQLDatastore extends Datastore {
|
||||
boolean onResult(ResultSet resultSet) throws SQLException {
|
||||
if (resultSet.next()) {
|
||||
user.setName(resultSet.getString("name"));
|
||||
user.getNodes().putAll(gson.fromJson(resultSet.getString("perms"), NM_TYPE));
|
||||
user.setNodes(gson.fromJson(resultSet.getString("perms"), NM_TYPE));
|
||||
user.setPrimaryGroup(resultSet.getString("primary_group"));
|
||||
return true;
|
||||
}
|
||||
@@ -193,7 +193,7 @@ abstract class SQLDatastore extends Datastore {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
user.getNodes().putAll(gson.fromJson(resultSet.getString("perms"), NM_TYPE));
|
||||
user.setNodes(gson.fromJson(resultSet.getString("perms"), NM_TYPE));
|
||||
user.setPrimaryGroup(resultSet.getString("primary_group"));
|
||||
|
||||
if (!resultSet.getString("name").equals(user.getName())) {
|
||||
@@ -251,7 +251,7 @@ abstract class SQLDatastore extends Datastore {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
group.getNodes().putAll(gson.fromJson(resultSet.getString("perms"), NM_TYPE));
|
||||
group.setNodes(gson.fromJson(resultSet.getString("perms"), NM_TYPE));
|
||||
}
|
||||
return success;
|
||||
}
|
||||
@@ -273,7 +273,7 @@ abstract class SQLDatastore extends Datastore {
|
||||
@Override
|
||||
boolean onResult(ResultSet resultSet) throws SQLException {
|
||||
if (resultSet.next()) {
|
||||
group.getNodes().putAll(gson.fromJson(resultSet.getString("perms"), NM_TYPE));
|
||||
group.setNodes(gson.fromJson(resultSet.getString("perms"), NM_TYPE));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -297,7 +297,7 @@ abstract class SQLDatastore extends Datastore {
|
||||
boolean onResult(ResultSet resultSet) throws SQLException {
|
||||
while (resultSet.next()) {
|
||||
Group group = plugin.getGroupManager().make(resultSet.getString("name"));
|
||||
group.getNodes().putAll(gson.fromJson(resultSet.getString("perms"), NM_TYPE));
|
||||
group.setNodes(gson.fromJson(resultSet.getString("perms"), NM_TYPE));
|
||||
groups.add(group);
|
||||
}
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user