mirror of
https://github.com/LuckPerms/LuckPerms.git
synced 2025-01-15 21:01:34 +01:00
Add support for MongoDB and H2 database formats
This commit is contained in:
parent
31cef46b56
commit
a15a0752f4
@ -30,7 +30,7 @@ A permissions implementation for Bukkit/Spigot, BungeeCord and Sponge.
|
||||
* **Open Sourced, Free...** - you shouldn't have to pay $10+ for a "powerful" permissions plugin.
|
||||
* **BungeeCord compatible** - permissions, users and groups are synced across all LuckPerms instances
|
||||
* **Sponge compatible** - permissions, users and groups are synced across all LuckPerms instances (bukkit --> sponge, for example)
|
||||
* **Support for MySQL, SQLite & Flatfile (JSON)** - other storage methods coming soon (maybe)
|
||||
* **Support for MySQL, MongoDB, SQLite, H2 & Flatfile (JSON)** - other storage methods coming soon (maybe)
|
||||
|
||||
## Setup
|
||||
All configuration options are in the **config.yml/luckperms.conf** file, which is generated automagically when the plugin first starts.
|
||||
|
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luckperms</artifactId>
|
||||
<groupId>me.lucko.luckperms</groupId>
|
||||
<version>2.3</version>
|
||||
<version>2.4</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
package me.lucko.luckperms.api;
|
||||
|
||||
import me.lucko.luckperms.api.data.DatastoreConfiguration;
|
||||
import me.lucko.luckperms.api.data.MySQLConfiguration;
|
||||
|
||||
/**
|
||||
@ -76,9 +77,17 @@ public interface LPConfiguration {
|
||||
|
||||
/**
|
||||
* @return the database values set in the configuration
|
||||
* @deprecated use {@link #getDatastoreConfig()}
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
@Deprecated
|
||||
MySQLConfiguration getDatabaseValues();
|
||||
|
||||
/**
|
||||
* @return the values set for data storage in the configuration
|
||||
*/
|
||||
DatastoreConfiguration getDatastoreConfig();
|
||||
|
||||
/**
|
||||
* @return the storage method string from the configuration
|
||||
*/
|
||||
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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.api.data;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public interface DatastoreConfiguration extends MySQLConfiguration {
|
||||
|
||||
String getAddress();
|
||||
String getDatabase();
|
||||
String getUsername();
|
||||
String getPassword();
|
||||
|
||||
}
|
@ -22,6 +22,10 @@
|
||||
|
||||
package me.lucko.luckperms.api.data;
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link DatastoreConfiguration}. This is now used by multiple datastores, not just MySQL.
|
||||
*/
|
||||
@Deprecated
|
||||
public interface MySQLConfiguration {
|
||||
|
||||
String getAddress();
|
||||
|
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luckperms</artifactId>
|
||||
<groupId>me.lucko.luckperms</groupId>
|
||||
<version>2.3</version>
|
||||
<version>2.4</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@ -43,7 +43,12 @@
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<minimizeJar>true</minimizeJar>
|
||||
<minimizeJar>false</minimizeJar>
|
||||
<artifactSet>
|
||||
<excludes>
|
||||
<exclude>org.xerial:*</exclude>
|
||||
</excludes>
|
||||
</artifactSet>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>org.slf4j</pattern>
|
||||
@ -53,6 +58,18 @@
|
||||
<pattern>com.zaxxer.hikari</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.hikari</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.mongodb</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.mongodb</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.bson</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.bson</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.h2</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.h2</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
</configuration>
|
||||
</execution>
|
||||
@ -105,20 +122,6 @@
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<!-- HikariCP -->
|
||||
<dependency>
|
||||
<groupId>com.zaxxer</groupId>
|
||||
<artifactId>HikariCP</artifactId>
|
||||
<version>2.4.7</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<!-- slf4j library -->
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-simple</artifactId>
|
||||
<version>1.7.9</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<!-- Lombok -->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
|
@ -35,9 +35,7 @@ import me.lucko.luckperms.data.Importer;
|
||||
import me.lucko.luckperms.groups.GroupManager;
|
||||
import me.lucko.luckperms.runnables.UpdateTask;
|
||||
import me.lucko.luckperms.storage.Datastore;
|
||||
import me.lucko.luckperms.storage.methods.FlatfileDatastore;
|
||||
import me.lucko.luckperms.storage.methods.MySQLDatastore;
|
||||
import me.lucko.luckperms.storage.methods.SQLiteDatastore;
|
||||
import me.lucko.luckperms.storage.StorageFactory;
|
||||
import me.lucko.luckperms.tracks.TrackManager;
|
||||
import me.lucko.luckperms.users.BukkitUserManager;
|
||||
import me.lucko.luckperms.users.UserManager;
|
||||
@ -83,24 +81,7 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
||||
main.setTabCompleter(commandManager);
|
||||
main.setAliases(Arrays.asList("perms", "lp", "permissions", "p", "perm"));
|
||||
|
||||
getLog().info("Detecting storage method...");
|
||||
final String storageMethod = configuration.getStorageMethod();
|
||||
if (storageMethod.equalsIgnoreCase("mysql")) {
|
||||
getLog().info("Using MySQL as storage method.");
|
||||
datastore = new MySQLDatastore(this, configuration.getDatabaseValues());
|
||||
} else if (storageMethod.equalsIgnoreCase("sqlite")) {
|
||||
getLog().info("Using SQLite as storage method.");
|
||||
datastore = new SQLiteDatastore(this, new File(getDataFolder(), "luckperms.sqlite"));
|
||||
} else if (storageMethod.equalsIgnoreCase("flatfile")) {
|
||||
getLog().info("Using Flatfile (JSON) as storage method.");
|
||||
datastore = new FlatfileDatastore(this, getDataFolder());
|
||||
} else {
|
||||
getLog().severe("Storage method '" + storageMethod + "' was not recognised. Using SQLite as fallback.");
|
||||
datastore = new SQLiteDatastore(this, new File(getDataFolder(), "luckperms.sqlite"));
|
||||
}
|
||||
|
||||
getLog().info("Initialising datastore...");
|
||||
datastore.init();
|
||||
datastore = StorageFactory.getDatastore(this, "sqlite");
|
||||
|
||||
getLog().info("Loading internal permission managers...");
|
||||
uuidCache = new UuidCache(getConfiguration().getOnlineMode());
|
||||
@ -197,6 +178,11 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
||||
return getServer().getOnlinePlayers().stream().map(p -> BukkitSenderFactory.get().wrap(p)).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sender getConsoleSender() {
|
||||
return BukkitSenderFactory.get().wrap(getServer().getConsoleSender());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getPossiblePermissions() {
|
||||
final List<String> perms = new ArrayList<>();
|
||||
|
@ -1,4 +1,9 @@
|
||||
# LuckPerms Configuration
|
||||
##############################################################################
|
||||
# +------------------------------------------------------------------------+ #
|
||||
# | LuckPerms Configuration | #
|
||||
# | https://github.com/lucko/LuckPerms | #
|
||||
# +------------------------------------------------------------------------+ #
|
||||
##############################################################################
|
||||
|
||||
# The name of the server, used for server specific permissions. Set to 'global' to disable.
|
||||
server: global
|
||||
@ -38,13 +43,16 @@ apply-regex: true
|
||||
apply-shorthand: true
|
||||
|
||||
# Which storage method the plugin should use.
|
||||
# Currently supported: mysql, sqlite, flatfile
|
||||
# Fill out connection info below if you're using MySQL
|
||||
storage-method: sqlite
|
||||
# Currently supported: mysql, sqlite, h2, flatfile, mongodb
|
||||
# Fill out connection info below if you're using MySQL or MongoDB
|
||||
storage-method: h2
|
||||
|
||||
sql:
|
||||
data:
|
||||
address: localhost:3306
|
||||
database: minecraft
|
||||
username: root
|
||||
password: ''
|
||||
|
||||
# Set to -1 to disable. If this is the only instance accessing the datastore, you can disable syncing.
|
||||
# e.g. if you're using sqlite or flatfile, this can be set to -1 to save resources.
|
||||
sync-minutes: 3
|
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luckperms</artifactId>
|
||||
<groupId>me.lucko.luckperms</groupId>
|
||||
<version>2.3</version>
|
||||
<version>2.4</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@ -43,7 +43,7 @@
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<minimizeJar>true</minimizeJar>
|
||||
<minimizeJar>false</minimizeJar>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>org.slf4j</pattern>
|
||||
@ -53,6 +53,18 @@
|
||||
<pattern>com.zaxxer.hikari</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.hikari</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.mongodb</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.mongodb</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.bson</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.bson</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.h2</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.h2</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
</configuration>
|
||||
</execution>
|
||||
@ -98,20 +110,6 @@
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<!-- HikariCP -->
|
||||
<dependency>
|
||||
<groupId>com.zaxxer</groupId>
|
||||
<artifactId>HikariCP</artifactId>
|
||||
<version>2.4.7</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<!-- slf4j library -->
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-simple</artifactId>
|
||||
<version>1.7.9</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<!-- Lombok -->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
|
@ -34,8 +34,7 @@ import me.lucko.luckperms.data.Importer;
|
||||
import me.lucko.luckperms.groups.GroupManager;
|
||||
import me.lucko.luckperms.runnables.UpdateTask;
|
||||
import me.lucko.luckperms.storage.Datastore;
|
||||
import me.lucko.luckperms.storage.methods.FlatfileDatastore;
|
||||
import me.lucko.luckperms.storage.methods.MySQLDatastore;
|
||||
import me.lucko.luckperms.storage.StorageFactory;
|
||||
import me.lucko.luckperms.tracks.TrackManager;
|
||||
import me.lucko.luckperms.users.BungeeUserManager;
|
||||
import me.lucko.luckperms.users.UserManager;
|
||||
@ -78,21 +77,7 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
|
||||
// disable the default Bungee /perms command so it gets handled by the Bukkit plugin
|
||||
getProxy().getDisabledCommands().add("perms");
|
||||
|
||||
getLog().info("Detecting storage method...");
|
||||
final String storageMethod = configuration.getStorageMethod();
|
||||
if (storageMethod.equalsIgnoreCase("mysql")) {
|
||||
getLog().info("Using MySQL as storage method.");
|
||||
datastore = new MySQLDatastore(this, configuration.getDatabaseValues());
|
||||
} else if (storageMethod.equalsIgnoreCase("flatfile")) {
|
||||
getLog().info("Using Flatfile (JSON) as storage method.");
|
||||
datastore = new FlatfileDatastore(this, getDataFolder());
|
||||
} else {
|
||||
getLog().severe("Storage method '" + storageMethod + "' was not recognised. Using Flatfile as fallback.");
|
||||
datastore = new FlatfileDatastore(this, getDataFolder());
|
||||
}
|
||||
|
||||
getLog().info("Initialising datastore...");
|
||||
datastore.init();
|
||||
datastore = StorageFactory.getDatastore(this, "h2");
|
||||
|
||||
getLog().info("Loading internal permission managers...");
|
||||
uuidCache = new UuidCache(getConfiguration().getOnlineMode());
|
||||
@ -162,6 +147,11 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
|
||||
return getProxy().getPlayers().stream().map(p -> BungeeSenderFactory.get().wrap(p)).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sender getConsoleSender() {
|
||||
return BungeeSenderFactory.get().wrap(getProxy().getConsole());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getPossiblePermissions() {
|
||||
// No such thing on Bungee. Wildcards are processed in the listener instead.
|
||||
|
@ -1,4 +1,9 @@
|
||||
# LuckPerms Configuration
|
||||
##############################################################################
|
||||
# +------------------------------------------------------------------------+ #
|
||||
# | LuckPerms Configuration | #
|
||||
# | https://github.com/lucko/LuckPerms | #
|
||||
# +------------------------------------------------------------------------+ #
|
||||
##############################################################################
|
||||
|
||||
# The name of the server, used for server specific permissions. Set to 'global' to disable.
|
||||
server: bungee
|
||||
@ -38,13 +43,16 @@ apply-regex: true
|
||||
apply-shorthand: true
|
||||
|
||||
# Which storage method the plugin should use.
|
||||
# Currently supported: mysql & flatfile
|
||||
# Fill out connection info below if you're using MySQL
|
||||
storage-method: flatfile
|
||||
# Currently supported: mysql, sqlite, h2, flatfile, mongodb
|
||||
# Fill out connection info below if you're using MySQL or MongoDB
|
||||
storage-method: h2
|
||||
|
||||
sql:
|
||||
data:
|
||||
address: localhost:3306
|
||||
database: minecraft
|
||||
username: root
|
||||
password: ''
|
||||
|
||||
# Set to -1 to disable. If this is the only instance accessing the datastore, you can disable syncing.
|
||||
# e.g. if you're using sqlite or flatfile, this can be set to -1 to save resources.
|
||||
sync-minutes: 3
|
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luckperms</artifactId>
|
||||
<groupId>me.lucko.luckperms</groupId>
|
||||
<version>2.3</version>
|
||||
<version>2.4</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@ -39,6 +39,27 @@
|
||||
<version>2.4.7</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<!-- SQLite -->
|
||||
<dependency>
|
||||
<groupId>org.xerial</groupId>
|
||||
<artifactId>sqlite-jdbc</artifactId>
|
||||
<version>3.8.11.2</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<!-- H2 -->
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<version>1.4.192</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<!-- MongoDB -->
|
||||
<dependency>
|
||||
<groupId>org.mongodb</groupId>
|
||||
<artifactId>mongo-java-driver</artifactId>
|
||||
<version>3.3.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<!-- slf4j library -->
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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;
|
||||
|
2
pom.xml
2
pom.xml
@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>me.lucko.luckperms</groupId>
|
||||
<artifactId>luckperms</artifactId>
|
||||
<version>2.3</version>
|
||||
<version>2.4</version>
|
||||
<modules>
|
||||
<module>common</module>
|
||||
<module>api</module>
|
||||
|
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>luckperms</artifactId>
|
||||
<groupId>me.lucko.luckperms</groupId>
|
||||
<version>2.3</version>
|
||||
<version>2.4</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@ -43,12 +43,27 @@
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<minimizeJar>true</minimizeJar>
|
||||
<minimizeJar>false</minimizeJar>
|
||||
<artifactSet>
|
||||
<excludes>
|
||||
<exclude>org.slf4j:*</exclude>
|
||||
<exclude>org.xerial:*</exclude>
|
||||
<exclude>com.h2database:*</exclude>
|
||||
</excludes>
|
||||
</artifactSet>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>com.zaxxer.hikari</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.hikari</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.mongodb</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.mongodb</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.bson</pattern>
|
||||
<shadedPattern>me.lucko.luckperms.lib.bson</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
</configuration>
|
||||
</execution>
|
||||
@ -128,13 +143,6 @@
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<!-- HikariCP -->
|
||||
<dependency>
|
||||
<groupId>com.zaxxer</groupId>
|
||||
<artifactId>HikariCP</artifactId>
|
||||
<version>2.4.7</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<!-- javassist maven -->
|
||||
<dependency>
|
||||
<groupId>de.icongmbh.oss.maven.plugins</groupId>
|
||||
|
@ -35,9 +35,7 @@ import me.lucko.luckperms.data.Importer;
|
||||
import me.lucko.luckperms.groups.GroupManager;
|
||||
import me.lucko.luckperms.runnables.UpdateTask;
|
||||
import me.lucko.luckperms.storage.Datastore;
|
||||
import me.lucko.luckperms.storage.methods.FlatfileDatastore;
|
||||
import me.lucko.luckperms.storage.methods.MySQLDatastore;
|
||||
import me.lucko.luckperms.storage.methods.SQLiteDatastore;
|
||||
import me.lucko.luckperms.storage.StorageFactory;
|
||||
import me.lucko.luckperms.tracks.TrackManager;
|
||||
import me.lucko.luckperms.users.SpongeUserManager;
|
||||
import me.lucko.luckperms.users.UserManager;
|
||||
@ -106,24 +104,7 @@ public class LPSpongePlugin implements LuckPermsPlugin {
|
||||
SpongeCommand commandManager = new SpongeCommand(this);
|
||||
cmdService.register(this, commandManager, "luckperms", "perms", "lp", "permissions", "p", "perm");
|
||||
|
||||
getLog().info("Detecting storage method...");
|
||||
final String storageMethod = configuration.getStorageMethod();
|
||||
if (storageMethod.equalsIgnoreCase("mysql")) {
|
||||
getLog().info("Using MySQL as storage method.");
|
||||
datastore = new MySQLDatastore(this, configuration.getDatabaseValues());
|
||||
} else if (storageMethod.equalsIgnoreCase("sqlite")) {
|
||||
getLog().info("Using SQLite as storage method.");
|
||||
datastore = new SQLiteDatastore(this, new File(getMainDir(), "luckperms.sqlite"));
|
||||
} else if (storageMethod.equalsIgnoreCase("flatfile")) {
|
||||
getLog().info("Using Flatfile (JSON) as storage method.");
|
||||
datastore = new FlatfileDatastore(this, getMainDir());
|
||||
} else {
|
||||
getLog().severe("Storage method '" + storageMethod + "' was not recognised. Using SQLite as fallback.");
|
||||
datastore = new SQLiteDatastore(this, new File(getMainDir(), "luckperms.sqlite"));
|
||||
}
|
||||
|
||||
getLog().info("Initialising datastore...");
|
||||
datastore.init();
|
||||
datastore = StorageFactory.getDatastore(this, "h2");
|
||||
|
||||
getLog().info("Loading internal permission managers...");
|
||||
uuidCache = new UuidCache(getConfiguration().getOnlineMode());
|
||||
@ -196,6 +177,11 @@ public class LPSpongePlugin implements LuckPermsPlugin {
|
||||
return luckPermsDir;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getDataFolder() {
|
||||
return getMainDir();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return "null";
|
||||
@ -221,6 +207,11 @@ public class LPSpongePlugin implements LuckPermsPlugin {
|
||||
return game.getServer().getOnlinePlayers().stream().map(s -> SpongeSenderFactory.get().wrap(s)).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sender getConsoleSender() {
|
||||
return SpongeSenderFactory.get().wrap(game.getServer().getConsole());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getPossiblePermissions() {
|
||||
Optional<PermissionService> p = game.getServiceManager().provide(PermissionService.class);
|
||||
|
@ -1,4 +1,9 @@
|
||||
# LuckPerms Configuration
|
||||
##############################################################################
|
||||
# +------------------------------------------------------------------------+ #
|
||||
# | LuckPerms Configuration | #
|
||||
# | https://github.com/lucko/LuckPerms | #
|
||||
# +------------------------------------------------------------------------+ #
|
||||
##############################################################################
|
||||
|
||||
# The name of the server, used for server specific permissions. Set to 'global' to disable.
|
||||
server="global"
|
||||
@ -38,14 +43,17 @@ apply-regex=true
|
||||
apply-shorthand=true
|
||||
|
||||
# Which storage method the plugin should use.
|
||||
# Currently supported: mysql, sqlite, flatfile
|
||||
# Fill out connection info below if you're using MySQL
|
||||
storage-method="sqlite"
|
||||
# Currently supported: mysql, sqlite, h2, flatfile, mongodb
|
||||
# Fill out connection info below if you're using MySQL or MongoDB
|
||||
storage-method="h2"
|
||||
|
||||
sql: {
|
||||
data: {
|
||||
address="localhost:3306"
|
||||
database="minecraft"
|
||||
username="root"
|
||||
password=""
|
||||
|
||||
# Set to -1 to disable. If this is the only instance accessing the datastore, you can disable syncing.
|
||||
# e.g. if you're using sqlite or flatfile, this can be set to -1 to save resources.
|
||||
sync-minutes=3
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user