mirror of
https://github.com/LuckPerms/LuckPerms.git
synced 2025-01-01 05:57:51 +01:00
WIP: implement better sql schema - towards #77
This commit is contained in:
parent
d34013396a
commit
6874cfd5b1
@ -74,6 +74,13 @@
|
||||
<version>1.4.192</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- PostgreSQL -->
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>9.4.1212</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- MongoDB -->
|
||||
<dependency>
|
||||
<groupId>org.mongodb</groupId>
|
||||
|
@ -30,6 +30,7 @@ import lombok.Getter;
|
||||
public enum Dependency {
|
||||
|
||||
MYSQL_DRIVER("https://repo1.maven.org/maven2/mysql/mysql-connector-java/5.1.6/mysql-connector-java-5.1.6.jar", "5.1.6", "com.mysql.jdbc.jdbc2.optional.MysqlDataSource"),
|
||||
POSTGRESQL_DRIVER("https://repo1.maven.org/maven2/org/postgresql/postgresql/9.4.1212/postgresql-9.4.1212.jar", "9.4.1212", "org.postgresql.ds.PGSimpleDataSource"),
|
||||
H2_DRIVER("https://repo1.maven.org/maven2/com/h2database/h2/1.4.193/h2-1.4.193.jar", "1.4.193", "org.h2.Driver"),
|
||||
SQLITE_DRIVER("https://repo1.maven.org/maven2/org/xerial/sqlite-jdbc/3.15.1/sqlite-jdbc-3.15.1.jar", "3.15.1", "org.sqlite.JDBC"),
|
||||
HIKARI("https://repo1.maven.org/maven2/com/zaxxer/HikariCP/2.5.1/HikariCP-2.5.1.jar", "2.5.1", "com.zaxxer.hikari.HikariDataSource"),
|
||||
|
@ -60,6 +60,7 @@ public class DependencyManager {
|
||||
.put(StorageType.YAML, ImmutableList.of())
|
||||
.put(StorageType.MONGODB, ImmutableList.of(Dependency.MONGODB_DRIVER))
|
||||
.put(StorageType.MYSQL, ImmutableList.of(Dependency.MYSQL_DRIVER, Dependency.SLF4J_API, Dependency.SLF4J_SIMPLE, Dependency.HIKARI))
|
||||
.put(StorageType.POSTGRESQL, ImmutableList.of(Dependency.POSTGRESQL_DRIVER, Dependency.SLF4J_API, Dependency.SLF4J_SIMPLE, Dependency.HIKARI))
|
||||
.put(StorageType.SQLITE, ImmutableList.of(Dependency.SQLITE_DRIVER))
|
||||
.put(StorageType.H2, ImmutableList.of(Dependency.H2_DRIVER))
|
||||
.build();
|
||||
|
@ -30,7 +30,7 @@ import me.lucko.luckperms.common.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.storage.backing.AbstractBacking;
|
||||
import me.lucko.luckperms.common.storage.backing.JSONBacking;
|
||||
import me.lucko.luckperms.common.storage.backing.MongoDBBacking;
|
||||
import me.lucko.luckperms.common.storage.backing.SQLBacking;
|
||||
import me.lucko.luckperms.common.storage.backing.SQLLegacyBacking;
|
||||
import me.lucko.luckperms.common.storage.backing.YAMLBacking;
|
||||
import me.lucko.luckperms.common.storage.backing.sqlprovider.H2Provider;
|
||||
import me.lucko.luckperms.common.storage.backing.sqlprovider.MySQLProvider;
|
||||
@ -120,11 +120,11 @@ public class StorageFactory {
|
||||
private static AbstractBacking makeBacking(StorageType method, LuckPermsPlugin plugin) {
|
||||
switch (method) {
|
||||
case MYSQL:
|
||||
return new SQLBacking(plugin, new MySQLProvider(plugin.getConfiguration().getDatabaseValues()));
|
||||
return new SQLLegacyBacking(plugin, new MySQLProvider(plugin.getConfiguration().getDatabaseValues()));
|
||||
case SQLITE:
|
||||
return new SQLBacking(plugin, new SQLiteProvider(new File(plugin.getDataFolder(), "luckperms.sqlite")));
|
||||
return new SQLLegacyBacking(plugin, new SQLiteProvider(new File(plugin.getDataFolder(), "luckperms.sqlite")));
|
||||
case H2:
|
||||
return new SQLBacking(plugin, new H2Provider(new File(plugin.getDataFolder(), "luckperms.db")));
|
||||
return new SQLLegacyBacking(plugin, new H2Provider(new File(plugin.getDataFolder(), "luckperms.db")));
|
||||
case MONGODB:
|
||||
return new MongoDBBacking(plugin, plugin.getConfiguration().getDatabaseValues());
|
||||
case YAML:
|
||||
|
@ -34,6 +34,7 @@ public enum StorageType {
|
||||
YAML("yaml", "yml"),
|
||||
MONGODB("mongodb"),
|
||||
MYSQL("mysql"),
|
||||
POSTGRESQL("postgresql"),
|
||||
SQLITE("sqlite"),
|
||||
H2("h2");
|
||||
|
||||
|
@ -22,106 +22,76 @@
|
||||
|
||||
package me.lucko.luckperms.common.storage.backing;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
import me.lucko.luckperms.api.LogEntry;
|
||||
import me.lucko.luckperms.api.Node;
|
||||
import me.lucko.luckperms.common.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.core.UserIdentifier;
|
||||
import me.lucko.luckperms.common.core.model.Group;
|
||||
import me.lucko.luckperms.common.core.model.Track;
|
||||
import me.lucko.luckperms.common.core.model.User;
|
||||
import me.lucko.luckperms.common.data.Log;
|
||||
import me.lucko.luckperms.common.managers.GroupManager;
|
||||
import me.lucko.luckperms.common.managers.TrackManager;
|
||||
import me.lucko.luckperms.common.managers.impl.GenericUserManager;
|
||||
import me.lucko.luckperms.common.storage.backing.sqlprovider.H2Provider;
|
||||
import me.lucko.luckperms.common.storage.backing.sqlprovider.MySQLProvider;
|
||||
import me.lucko.luckperms.common.storage.backing.sqlprovider.SQLProvider;
|
||||
import me.lucko.luckperms.common.storage.backing.sqlprovider.SQLiteProvider;
|
||||
import me.lucko.luckperms.common.storage.backing.utils.NodeDataHolder;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.lang.reflect.Type;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import static me.lucko.luckperms.common.core.model.PermissionHolder.exportToLegacy;
|
||||
import static me.lucko.luckperms.common.storage.backing.sqlprovider.SQLProvider.QueryPS;
|
||||
import static me.lucko.luckperms.common.storage.backing.sqlprovider.SQLProvider.QueryRS;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class SQLBacking extends AbstractBacking {
|
||||
private static final Type NM_TYPE = new TypeToken<Map<String, Boolean>>() {}.getType();
|
||||
private static final Type T_TYPE = new TypeToken<List<String>>() {}.getType();
|
||||
|
||||
private static final String MYSQL_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 MYSQL_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 MYSQL_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 MYSQL_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 MYSQL_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 static final Type LIST_STRING_TYPE = new TypeToken<List<String>>() {}.getType();
|
||||
|
||||
private static final String H2_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 H2_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 H2_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 H2_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 H2_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 static final String USER_PERMISSIONS_SELECT = "SELECT permission, value, server, world, expiry, contexts FROM {prefix}user_permissions WHERE uuid=?";
|
||||
private static final String USER_PERMISSIONS_DELETE = "DELETE FROM {prefix}user_permissions WHERE uuid=?";
|
||||
private static final String USER_PERMISSIONS_INSERT = "INSERT INTO {prefix}user_permissions VALUES(?, ?, ?, ?, ?, ?, ?)";
|
||||
private static final String USER_PERMISSIONS_SELECT_DISTINCT = "SELECT DISTINCT uuid FROM {prefix}user_permissions";
|
||||
|
||||
private static final String SQLITE_CREATETABLE_UUID = "CREATE TABLE IF NOT EXISTS `lp_uuid` (`name` VARCHAR(16) NOT NULL, `uuid` VARCHAR(36) NOT NULL, PRIMARY KEY (`name`));";
|
||||
private static final String SQLITE_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`));";
|
||||
private static final String SQLITE_CREATETABLE_GROUPS = "CREATE TABLE IF NOT EXISTS `lp_groups` (`name` VARCHAR(36) NOT NULL, `perms` TEXT NULL, PRIMARY KEY (`name`));";
|
||||
private static final String SQLITE_CREATETABLE_TRACKS = "CREATE TABLE IF NOT EXISTS `lp_tracks` (`name` VARCHAR(36) NOT NULL, `groups` TEXT NULL, PRIMARY KEY (`name`));";
|
||||
private static final String SQLITE_CREATETABLE_ACTION = "CREATE TABLE IF NOT EXISTS `lp_actions` (`id` INTEGER PRIMARY KEY NOT NULL, `time` BIG INT 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);";
|
||||
|
||||
private static final Map<Class<? extends SQLProvider>, String[]> INIT_QUERIES = ImmutableMap.<Class<? extends SQLProvider>, String[]>builder()
|
||||
.put(MySQLProvider.class, new String[]{MYSQL_CREATETABLE_UUID, MYSQL_CREATETABLE_USERS, MYSQL_CREATETABLE_GROUPS, MYSQL_CREATETABLE_TRACKS, MYSQL_CREATETABLE_ACTION})
|
||||
.put(H2Provider.class, new String[]{H2_CREATETABLE_UUID, H2_CREATETABLE_USERS, H2_CREATETABLE_GROUPS, H2_CREATETABLE_TRACKS, H2_CREATETABLE_ACTION})
|
||||
.put(SQLiteProvider.class, new String[]{SQLITE_CREATETABLE_UUID, SQLITE_CREATETABLE_USERS, SQLITE_CREATETABLE_GROUPS, SQLITE_CREATETABLE_TRACKS, SQLITE_CREATETABLE_ACTION})
|
||||
.build();
|
||||
|
||||
private static final String USER_INSERT = "INSERT INTO lp_users VALUES(?, ?, ?, ?)";
|
||||
private static final String USER_SELECT = "SELECT * FROM lp_users WHERE uuid=?";
|
||||
private static final String USER_SELECT_ALL = "SELECT uuid FROM lp_users";
|
||||
private static final String USER_UPDATE = "UPDATE lp_users SET name=?, primary_group = ?, perms=? WHERE uuid=?";
|
||||
private static final String USER_DELETE = "DELETE FROM lp_users WHERE uuid=?";
|
||||
private static final String USER_DELETE_ALL = "DELETE FROM lp_users WHERE perms=?";
|
||||
private static final String PLAYER_SELECT = "SELECT username, primary_group FROM {prefix}players WHERE uuid=?";
|
||||
|
||||
private static final String GROUP_INSERT = "INSERT INTO lp_groups VALUES(?, ?)";
|
||||
private static final String GROUP_SELECT = "SELECT perms FROM lp_groups WHERE name=?";
|
||||
private static final String GROUP_SELECT_ALL = "SELECT * FROM lp_groups";
|
||||
private static final String GROUP_UPDATE = "UPDATE lp_groups SET perms=? WHERE name=?";
|
||||
private static final String GROUP_DELETE = "DELETE FROM lp_groups WHERE name=?";
|
||||
private static final String TRACK_INSERT = "INSERT INTO {prefix}tracks VALUES(?, ?)";
|
||||
private static final String TRACK_SELECT = "SELECT groups FROM {prefix}tracks WHERE name=?";
|
||||
private static final String TRACK_SELECT_ALL = "SELECT * FROM {prefix}tracks";
|
||||
private static final String TRACK_UPDATE = "UPDATE {prefix}tracks SET groups=? WHERE name=?";
|
||||
private static final String TRACK_DELETE = "DELETE FROM {prefix}tracks WHERE name=?";
|
||||
|
||||
private static final String TRACK_INSERT = "INSERT INTO lp_tracks VALUES(?, ?)";
|
||||
private static final String TRACK_SELECT = "SELECT groups FROM lp_tracks WHERE name=?";
|
||||
private static final String TRACK_SELECT_ALL = "SELECT * FROM lp_tracks";
|
||||
private static final String TRACK_UPDATE = "UPDATE lp_tracks SET groups=? WHERE name=?";
|
||||
private static final String TRACK_DELETE = "DELETE FROM lp_tracks WHERE name=?";
|
||||
private static final String ACTION_INSERT = "INSERT INTO {prefix}actions(`time`, `actor_uuid`, `actor_name`, `type`, `acted_uuid`, `acted_name`, `action`) VALUES(?, ?, ?, ?, ?, ?, ?)";
|
||||
private static final String ACTION_SELECT_ALL = "SELECT * FROM {prefix}actions";
|
||||
|
||||
private static final String UUIDCACHE_INSERT = "INSERT INTO lp_uuid VALUES(?, ?)";
|
||||
private static final String UUIDCACHE_SELECT = "SELECT uuid FROM lp_uuid WHERE name=?";
|
||||
private static final String UUIDCACHE_SELECT_NAME = "SELECT name FROM lp_uuid WHERE uuid=?";
|
||||
private static final String UUIDCACHE_UPDATE = "UPDATE lp_uuid SET uuid=? WHERE name=?";
|
||||
|
||||
private static final String ACTION_INSERT = "INSERT INTO lp_actions(`time`, `actor_uuid`, `actor_name`, `type`, `acted_uuid`, `acted_name`, `action`) VALUES(?, ?, ?, ?, ?, ?, ?)";
|
||||
private static final String ACTION_SELECT_ALL = "SELECT * FROM lp_actions";
|
||||
|
||||
private final Gson gson;
|
||||
private final SQLProvider provider;
|
||||
private final Function<String, String> prefix;
|
||||
|
||||
public SQLBacking(LuckPermsPlugin plugin, SQLProvider provider) {
|
||||
public SQLBacking(LuckPermsPlugin plugin, SQLProvider provider, String prefix) {
|
||||
super(plugin, provider.getName());
|
||||
this.provider = provider;
|
||||
this.prefix = s -> s.replace("{prefix}", prefix);
|
||||
gson = new Gson();
|
||||
}
|
||||
|
||||
private boolean runQuery(String query, QueryPS queryPS) {
|
||||
private boolean runQuery(String query, SQLProvider.QueryPS queryPS) {
|
||||
return provider.runQuery(query, queryPS);
|
||||
}
|
||||
|
||||
private boolean runQuery(String query, QueryPS queryPS, QueryRS queryRS) {
|
||||
private boolean runQuery(String query, SQLProvider.QueryPS queryPS, SQLProvider.QueryRS queryRS) {
|
||||
return provider.runQuery(query, queryPS, queryRS);
|
||||
}
|
||||
|
||||
@ -129,17 +99,12 @@ public class SQLBacking extends AbstractBacking {
|
||||
return provider.runQuery(query);
|
||||
}
|
||||
|
||||
private boolean runQuery(String query, QueryRS queryRS) {
|
||||
private boolean runQuery(String query, SQLProvider.QueryRS queryRS) {
|
||||
return provider.runQuery(query, queryRS);
|
||||
}
|
||||
|
||||
private boolean setupTables(String[] tableQueries) {
|
||||
boolean success = true;
|
||||
for (String q : tableQueries) {
|
||||
if (!runQuery(q)) success = false;
|
||||
}
|
||||
|
||||
return success && cleanupUsers();
|
||||
public boolean tableExists(String table) throws SQLException {
|
||||
return provider.getConnection().getMetaData().getTables(null, null, table.toUpperCase(), null).next();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -147,15 +112,45 @@ public class SQLBacking extends AbstractBacking {
|
||||
try {
|
||||
provider.init();
|
||||
|
||||
if (!setupTables(INIT_QUERIES.get(provider.getClass()))) {
|
||||
plugin.getLog().severe("Error occurred whilst initialising the database.");
|
||||
shutdown();
|
||||
} else {
|
||||
setAcceptingLogins(true);
|
||||
// Init tables
|
||||
if (!tableExists(prefix + "user_permissions")) {
|
||||
String schemaFileName = "lp-schema-" + provider.getName().toLowerCase() + ".sql";
|
||||
try (InputStream is = plugin.getClass().getResourceAsStream("sql/" + schemaFileName)) {
|
||||
if (is == null) {
|
||||
throw new Exception("Couldn't locate schema file for " + provider.getName());
|
||||
}
|
||||
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
|
||||
try (Statement s = provider.getConnection().createStatement()) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
if (line.startsWith("--") || line.startsWith("#")) continue;
|
||||
|
||||
sb.append(line);
|
||||
|
||||
// check for end of declaration
|
||||
if (line.endsWith(";")) {
|
||||
sb.deleteCharAt(sb.length() - 1);
|
||||
|
||||
String result = prefix.apply(sb.toString().trim());
|
||||
if (!result.isEmpty()) s.addBatch(result);
|
||||
|
||||
// reset
|
||||
sb = new StringBuilder();
|
||||
}
|
||||
}
|
||||
s.executeBatch();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
setAcceptingLogins(true);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
plugin.getLog().severe("Error occurred whilst initialising the database.");
|
||||
shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
@ -170,7 +165,7 @@ public class SQLBacking extends AbstractBacking {
|
||||
|
||||
@Override
|
||||
public boolean logAction(LogEntry entry) {
|
||||
return runQuery(ACTION_INSERT, preparedStatement -> {
|
||||
return runQuery(prefix.apply(ACTION_INSERT), preparedStatement -> {
|
||||
preparedStatement.setLong(1, entry.getTimestamp());
|
||||
preparedStatement.setString(2, entry.getActor().toString());
|
||||
preparedStatement.setString(3, entry.getActorName());
|
||||
@ -184,7 +179,7 @@ public class SQLBacking extends AbstractBacking {
|
||||
@Override
|
||||
public Log getLog() {
|
||||
final Log.Builder log = Log.builder();
|
||||
boolean success = runQuery(ACTION_SELECT_ALL, resultSet -> {
|
||||
boolean success = runQuery(prefix.apply(ACTION_SELECT_ALL), resultSet -> {
|
||||
while (resultSet.next()) {
|
||||
final String actedUuid = resultSet.getString("acted_uuid");
|
||||
LogEntry e = new LogEntry(
|
||||
@ -208,56 +203,61 @@ public class SQLBacking extends AbstractBacking {
|
||||
User user = plugin.getUserManager().getOrMake(UserIdentifier.of(uuid, username));
|
||||
user.getIoLock().lock();
|
||||
try {
|
||||
// screw "effectively final"
|
||||
final String[] perms = new String[1];
|
||||
final String[] pg = new String[1];
|
||||
final String[] name = new String[1];
|
||||
final boolean[] exists = {false};
|
||||
|
||||
boolean s = runQuery(USER_SELECT,
|
||||
preparedStatement -> preparedStatement.setString(1, user.getUuid().toString()),
|
||||
resultSet -> {
|
||||
if (resultSet.next()) {
|
||||
// User exists.
|
||||
exists[0] = true;
|
||||
perms[0] = resultSet.getString("perms");
|
||||
pg[0] = resultSet.getString("primary_group");
|
||||
name[0] = resultSet.getString("name");
|
||||
List<NodeDataHolder> data = new ArrayList<>();
|
||||
AtomicReference<String> primaryGroup = new AtomicReference<>(null);
|
||||
AtomicReference<String> userName = new AtomicReference<>();
|
||||
boolean s = runQuery(
|
||||
prefix.apply(USER_PERMISSIONS_SELECT),
|
||||
ps -> ps.setString(1, user.getUuid().toString()),
|
||||
rs -> {
|
||||
while (rs.next()) {
|
||||
String permission = rs.getString("permission");
|
||||
boolean value = rs.getBoolean("value");
|
||||
String server = rs.getString("server");
|
||||
String world = rs.getString("world");
|
||||
long expiry = rs.getLong("expiry");
|
||||
String contexts = rs.getString("contexts");
|
||||
data.add(NodeDataHolder.of(permission, value, server, world, expiry, contexts));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
if (!s) {
|
||||
boolean s2 = runQuery(
|
||||
prefix.apply(PLAYER_SELECT),
|
||||
ps -> ps.setString(1, user.getUuid().toString()),
|
||||
rs -> {
|
||||
if (rs.next()) {
|
||||
userName.set(rs.getString("username"));
|
||||
primaryGroup.set(rs.getString("primary_group"));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
if (!s || !s2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (exists[0]) {
|
||||
// User exists, let's load.
|
||||
Map<String, Boolean> nodes = gson.fromJson(perms[0], NM_TYPE);
|
||||
|
||||
if (!data.isEmpty()) {
|
||||
Set<Node> nodes = data.stream().map(NodeDataHolder::toNode).collect(Collectors.toSet());
|
||||
user.setNodes(nodes);
|
||||
user.setPrimaryGroup(pg[0]);
|
||||
|
||||
boolean save = plugin.getUserManager().giveDefaultIfNeeded(user, false);
|
||||
String pg = primaryGroup.get();
|
||||
if (pg == null) {
|
||||
pg = "default";
|
||||
}
|
||||
|
||||
String name = userName.get();
|
||||
if (name == null) {
|
||||
name = "null";
|
||||
}
|
||||
|
||||
if (user.getName() == null || user.getName().equalsIgnoreCase("null")) {
|
||||
user.setName(name[0]);
|
||||
} else {
|
||||
if (!name[0].equals(user.getName())) {
|
||||
save = true;
|
||||
}
|
||||
user.setName(name);
|
||||
}
|
||||
|
||||
if (save) {
|
||||
String json = gson.toJson(exportToLegacy(user.getNodes()));
|
||||
runQuery(USER_UPDATE, preparedStatement -> {
|
||||
preparedStatement.setString(1, user.getName());
|
||||
preparedStatement.setString(2, user.getPrimaryGroup());
|
||||
preparedStatement.setString(3, json);
|
||||
preparedStatement.setString(4, user.getUuid().toString());
|
||||
});
|
||||
}
|
||||
user.setPrimaryGroup(pg);
|
||||
|
||||
} else {
|
||||
if (GenericUserManager.shouldSave(user)) {
|
||||
@ -276,55 +276,39 @@ public class SQLBacking extends AbstractBacking {
|
||||
|
||||
@Override
|
||||
public boolean saveUser(User user) {
|
||||
if (!GenericUserManager.shouldSave(user)) {
|
||||
user.getIoLock().lock();
|
||||
try {
|
||||
return runQuery(USER_DELETE, preparedStatement -> {
|
||||
preparedStatement.setString(1, user.getUuid().toString());
|
||||
});
|
||||
} finally {
|
||||
user.getIoLock().unlock();
|
||||
}
|
||||
}
|
||||
boolean shouldSave = GenericUserManager.shouldSave(user);
|
||||
|
||||
user.getIoLock().lock();
|
||||
try {
|
||||
final boolean[] exists = {false};
|
||||
boolean success = runQuery(USER_SELECT,
|
||||
preparedStatement -> preparedStatement.setString(1, user.getUuid().toString()),
|
||||
resultSet -> {
|
||||
if (resultSet.next()) {
|
||||
exists[0] = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
if (!success) {
|
||||
boolean s = runQuery(prefix.apply(USER_PERMISSIONS_DELETE), preparedStatement -> {
|
||||
preparedStatement.setString(1, user.getUuid().toString());
|
||||
});
|
||||
if (!s) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final String s = gson.toJson(exportToLegacy(user.getNodes()));
|
||||
|
||||
if (exists[0]) {
|
||||
// User exists, let's update.
|
||||
return runQuery(USER_UPDATE, preparedStatement -> {
|
||||
preparedStatement.setString(1, user.getName());
|
||||
preparedStatement.setString(2, user.getPrimaryGroup());
|
||||
preparedStatement.setString(3, s);
|
||||
preparedStatement.setString(4, user.getUuid().toString());
|
||||
});
|
||||
} else {
|
||||
// Doesn't already exist, let's insert.
|
||||
return runQuery(USER_INSERT, preparedStatement -> {
|
||||
preparedStatement.setString(1, user.getUuid().toString());
|
||||
preparedStatement.setString(2, user.getName());
|
||||
preparedStatement.setString(3, user.getPrimaryGroup());
|
||||
preparedStatement.setString(4, s);
|
||||
});
|
||||
if (!shouldSave) {
|
||||
return true;
|
||||
}
|
||||
|
||||
List<NodeDataHolder> data = user.getNodes().stream().map(NodeDataHolder::fromNode).collect(Collectors.toList());
|
||||
try (PreparedStatement ps = provider.getConnection().prepareStatement(prefix.apply(USER_PERMISSIONS_INSERT))) {
|
||||
for (NodeDataHolder nd : data) {
|
||||
ps.setString(1, user.getUuid().toString());
|
||||
ps.setString(2, nd.getPermission());
|
||||
ps.setBoolean(3, nd.isValue());
|
||||
ps.setString(4, nd.getServer());
|
||||
ps.setString(5, nd.getWorld());
|
||||
ps.setLong(6, nd.getExpiry());
|
||||
ps.setString(7, nd.getContexts());
|
||||
ps.addBatch();
|
||||
}
|
||||
ps.executeBatch();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return true;
|
||||
} finally {
|
||||
user.getIoLock().unlock();
|
||||
}
|
||||
@ -332,18 +316,16 @@ public class SQLBacking extends AbstractBacking {
|
||||
|
||||
@Override
|
||||
public boolean cleanupUsers() {
|
||||
return runQuery(USER_DELETE_ALL, preparedStatement -> {
|
||||
preparedStatement.setString(1, "{\"group.default\":true}");
|
||||
});
|
||||
return true; // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<UUID> getUniqueUsers() {
|
||||
Set<UUID> uuids = new HashSet<>();
|
||||
|
||||
boolean success = runQuery(USER_SELECT_ALL, resultSet -> {
|
||||
while (resultSet.next()) {
|
||||
String uuid = resultSet.getString("uuid");
|
||||
boolean success = runQuery(prefix.apply(USER_PERMISSIONS_SELECT_DISTINCT), rs -> {
|
||||
while (rs.next()) {
|
||||
String uuid = rs.getString("uuid");
|
||||
uuids.add(UUID.fromString(uuid));
|
||||
}
|
||||
return true;
|
||||
@ -354,134 +336,27 @@ public class SQLBacking extends AbstractBacking {
|
||||
|
||||
@Override
|
||||
public boolean createAndLoadGroup(String name) {
|
||||
Group group = plugin.getGroupManager().getOrMake(name);
|
||||
group.getIoLock().lock();
|
||||
try {
|
||||
final boolean[] exists = {false};
|
||||
final String[] perms = new String[1];
|
||||
|
||||
boolean s = runQuery(GROUP_SELECT,
|
||||
preparedStatement -> preparedStatement.setString(1, group.getName()),
|
||||
resultSet -> {
|
||||
if (resultSet.next()) {
|
||||
exists[0] = true;
|
||||
perms[0] = resultSet.getString("perms");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
if (!s) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (exists[0]) {
|
||||
// Group exists, let's load.
|
||||
Map<String, Boolean> nodes = gson.fromJson(perms[0], NM_TYPE);
|
||||
group.setNodes(nodes);
|
||||
return true;
|
||||
} else {
|
||||
String json = gson.toJson(exportToLegacy(group.getNodes()));
|
||||
return runQuery(GROUP_INSERT, preparedStatement -> {
|
||||
preparedStatement.setString(1, group.getName());
|
||||
preparedStatement.setString(2, json);
|
||||
});
|
||||
}
|
||||
|
||||
} finally {
|
||||
group.getIoLock().unlock();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadGroup(String name) {
|
||||
Group group = plugin.getGroupManager().getOrMake(name);
|
||||
group.getIoLock().lock();
|
||||
try {
|
||||
final String[] perms = new String[1];
|
||||
boolean s = runQuery(GROUP_SELECT,
|
||||
preparedStatement -> preparedStatement.setString(1, name),
|
||||
resultSet -> {
|
||||
if (resultSet.next()) {
|
||||
perms[0] = resultSet.getString("perms");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
if (!s) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Group exists, let's load.
|
||||
Map<String, Boolean> nodes = gson.fromJson(perms[0], NM_TYPE);
|
||||
group.setNodes(nodes);
|
||||
return true;
|
||||
|
||||
} finally {
|
||||
group.getIoLock().unlock();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadAllGroups() {
|
||||
List<String> groups = new ArrayList<>();
|
||||
boolean b = runQuery(GROUP_SELECT_ALL, resultSet -> {
|
||||
while (resultSet.next()) {
|
||||
String name = resultSet.getString("name");
|
||||
groups.add(name);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
if (!b) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (String g : groups) {
|
||||
if (!loadGroup(g)) {
|
||||
b = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (b) {
|
||||
GroupManager gm = plugin.getGroupManager();
|
||||
gm.getAll().values().stream()
|
||||
.filter(g -> !groups.contains(g.getName()))
|
||||
.forEach(gm::unload);
|
||||
}
|
||||
return b;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveGroup(Group group) {
|
||||
group.getIoLock().lock();
|
||||
try {
|
||||
String json = gson.toJson(exportToLegacy(group.getNodes()));
|
||||
return runQuery(GROUP_UPDATE, preparedStatement -> {
|
||||
preparedStatement.setString(1, json);
|
||||
preparedStatement.setString(2, group.getName());
|
||||
});
|
||||
} finally {
|
||||
group.getIoLock().unlock();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteGroup(Group group) {
|
||||
group.getIoLock().lock();
|
||||
boolean success;
|
||||
try {
|
||||
success = runQuery(GROUP_DELETE, preparedStatement -> {
|
||||
preparedStatement.setString(1, group.getName());
|
||||
});
|
||||
} finally {
|
||||
group.getIoLock().unlock();
|
||||
}
|
||||
|
||||
if (success) plugin.getGroupManager().unload(group);
|
||||
return success;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -489,15 +364,16 @@ public class SQLBacking extends AbstractBacking {
|
||||
Track track = plugin.getTrackManager().getOrMake(name);
|
||||
track.getIoLock().lock();
|
||||
try {
|
||||
final boolean[] exists = {false};
|
||||
final String[] groups = new String[1];
|
||||
AtomicBoolean exists = new AtomicBoolean(false);
|
||||
AtomicReference<String> groups = new AtomicReference<>(null);
|
||||
|
||||
boolean s = runQuery(TRACK_SELECT,
|
||||
preparedStatement -> preparedStatement.setString(1, track.getName()),
|
||||
resultSet -> {
|
||||
if (resultSet.next()) {
|
||||
exists[0] = true;
|
||||
groups[0] = resultSet.getString("groups");
|
||||
boolean s = runQuery(
|
||||
prefix.apply(TRACK_SELECT),
|
||||
ps -> ps.setString(1, track.getName()),
|
||||
rs -> {
|
||||
if (rs.next()) {
|
||||
exists.set(true);
|
||||
groups.set(rs.getString("groups"));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -507,9 +383,9 @@ public class SQLBacking extends AbstractBacking {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (exists[0]) {
|
||||
if (exists.get()) {
|
||||
// Track exists, let's load.
|
||||
track.setGroups(gson.fromJson(groups[0], T_TYPE));
|
||||
track.setGroups(gson.fromJson(groups.get(), LIST_STRING_TYPE));
|
||||
return true;
|
||||
} else {
|
||||
String json = gson.toJson(track.getGroups());
|
||||
@ -529,12 +405,13 @@ public class SQLBacking extends AbstractBacking {
|
||||
Track track = plugin.getTrackManager().getOrMake(name);
|
||||
track.getIoLock().lock();
|
||||
try {
|
||||
final String[] groups = {null};
|
||||
boolean s = runQuery(TRACK_SELECT,
|
||||
preparedStatement -> preparedStatement.setString(1, name),
|
||||
resultSet -> {
|
||||
if (resultSet.next()) {
|
||||
groups[0] = resultSet.getString("groups");
|
||||
AtomicReference<String> groups = new AtomicReference<>(null);
|
||||
boolean s = runQuery(
|
||||
TRACK_SELECT,
|
||||
ps -> ps.setString(1, name),
|
||||
rs -> {
|
||||
if (rs.next()) {
|
||||
groups.set(rs.getString("groups"));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -545,7 +422,7 @@ public class SQLBacking extends AbstractBacking {
|
||||
return false;
|
||||
}
|
||||
|
||||
track.setGroups(gson.fromJson(groups[0], T_TYPE));
|
||||
track.setGroups(gson.fromJson(groups.get(), LIST_STRING_TYPE));
|
||||
return true;
|
||||
|
||||
} finally {
|
||||
@ -556,13 +433,16 @@ public class SQLBacking extends AbstractBacking {
|
||||
@Override
|
||||
public boolean loadAllTracks() {
|
||||
List<String> tracks = new ArrayList<>();
|
||||
boolean b = runQuery(TRACK_SELECT_ALL, resultSet -> {
|
||||
while (resultSet.next()) {
|
||||
String name = resultSet.getString("name");
|
||||
tracks.add(name);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
boolean b = runQuery(
|
||||
prefix.apply(TRACK_SELECT_ALL),
|
||||
rs -> {
|
||||
while (rs.next()) {
|
||||
String name = rs.getString("name");
|
||||
tracks.add(name);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
if (!b) {
|
||||
return false;
|
||||
@ -588,10 +468,13 @@ public class SQLBacking extends AbstractBacking {
|
||||
track.getIoLock().lock();
|
||||
try {
|
||||
String s = gson.toJson(track.getGroups());
|
||||
return runQuery(TRACK_UPDATE, preparedStatement -> {
|
||||
preparedStatement.setString(1, s);
|
||||
preparedStatement.setString(2, track.getName());
|
||||
});
|
||||
return runQuery(
|
||||
prefix.apply(TRACK_UPDATE),
|
||||
ps -> {
|
||||
ps.setString(1, s);
|
||||
ps.setString(2, track.getName());
|
||||
}
|
||||
);
|
||||
} finally {
|
||||
track.getIoLock().unlock();
|
||||
}
|
||||
@ -602,9 +485,12 @@ public class SQLBacking extends AbstractBacking {
|
||||
track.getIoLock().lock();
|
||||
boolean success;
|
||||
try {
|
||||
success = runQuery(TRACK_DELETE, preparedStatement -> {
|
||||
preparedStatement.setString(1, track.getName());
|
||||
});
|
||||
success = runQuery(
|
||||
prefix.apply(TRACK_DELETE),
|
||||
ps -> {
|
||||
ps.setString(1, track.getName());
|
||||
}
|
||||
);
|
||||
} finally {
|
||||
track.getIoLock().unlock();
|
||||
}
|
||||
@ -615,70 +501,16 @@ public class SQLBacking extends AbstractBacking {
|
||||
|
||||
@Override
|
||||
public boolean saveUUIDData(String username, UUID uuid) {
|
||||
final String u = username.toLowerCase();
|
||||
final boolean[] update = {false};
|
||||
boolean s = runQuery(UUIDCACHE_SELECT,
|
||||
preparedStatement -> preparedStatement.setString(1, u),
|
||||
resultSet -> {
|
||||
if (resultSet.next()) {
|
||||
update[0] = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
if (!s) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (update[0]) {
|
||||
return runQuery(UUIDCACHE_UPDATE, preparedStatement -> {
|
||||
preparedStatement.setString(1, uuid.toString());
|
||||
preparedStatement.setString(2, u);
|
||||
});
|
||||
} else {
|
||||
return runQuery(UUIDCACHE_INSERT, preparedStatement -> {
|
||||
preparedStatement.setString(1, u);
|
||||
preparedStatement.setString(2, uuid.toString());
|
||||
});
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID(String username) {
|
||||
final String u = username.toLowerCase();
|
||||
final UUID[] uuid = {null};
|
||||
|
||||
boolean success = runQuery(UUIDCACHE_SELECT,
|
||||
preparedStatement -> preparedStatement.setString(1, u),
|
||||
resultSet -> {
|
||||
if (resultSet.next()) {
|
||||
uuid[0] = UUID.fromString(resultSet.getString("uuid"));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
return success ? uuid[0] : null;
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName(UUID uuid) {
|
||||
final String u = uuid.toString();
|
||||
final String[] name = {null};
|
||||
|
||||
boolean success = runQuery(UUIDCACHE_SELECT_NAME,
|
||||
preparedStatement -> preparedStatement.setString(1, u),
|
||||
resultSet -> {
|
||||
if (resultSet.next()) {
|
||||
name[0] = resultSet.getString("name");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
return success ? name[0] : null;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,685 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.storage.backing;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
import me.lucko.luckperms.api.LogEntry;
|
||||
import me.lucko.luckperms.common.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.core.UserIdentifier;
|
||||
import me.lucko.luckperms.common.core.model.Group;
|
||||
import me.lucko.luckperms.common.core.model.Track;
|
||||
import me.lucko.luckperms.common.core.model.User;
|
||||
import me.lucko.luckperms.common.data.Log;
|
||||
import me.lucko.luckperms.common.managers.GroupManager;
|
||||
import me.lucko.luckperms.common.managers.TrackManager;
|
||||
import me.lucko.luckperms.common.managers.impl.GenericUserManager;
|
||||
import me.lucko.luckperms.common.storage.backing.sqlprovider.H2Provider;
|
||||
import me.lucko.luckperms.common.storage.backing.sqlprovider.MySQLProvider;
|
||||
import me.lucko.luckperms.common.storage.backing.sqlprovider.SQLProvider;
|
||||
import me.lucko.luckperms.common.storage.backing.sqlprovider.SQLiteProvider;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import static me.lucko.luckperms.common.core.model.PermissionHolder.exportToLegacy;
|
||||
import static me.lucko.luckperms.common.storage.backing.sqlprovider.SQLProvider.QueryPS;
|
||||
import static me.lucko.luckperms.common.storage.backing.sqlprovider.SQLProvider.QueryRS;
|
||||
|
||||
public class SQLLegacyBacking extends AbstractBacking {
|
||||
private static final Type NM_TYPE = new TypeToken<Map<String, Boolean>>() {}.getType();
|
||||
private static final Type T_TYPE = new TypeToken<List<String>>() {}.getType();
|
||||
|
||||
private static final String MYSQL_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 MYSQL_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 MYSQL_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 MYSQL_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 MYSQL_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 static final String H2_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 H2_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 H2_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 H2_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 H2_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 static final String SQLITE_CREATETABLE_UUID = "CREATE TABLE IF NOT EXISTS `lp_uuid` (`name` VARCHAR(16) NOT NULL, `uuid` VARCHAR(36) NOT NULL, PRIMARY KEY (`name`));";
|
||||
private static final String SQLITE_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`));";
|
||||
private static final String SQLITE_CREATETABLE_GROUPS = "CREATE TABLE IF NOT EXISTS `lp_groups` (`name` VARCHAR(36) NOT NULL, `perms` TEXT NULL, PRIMARY KEY (`name`));";
|
||||
private static final String SQLITE_CREATETABLE_TRACKS = "CREATE TABLE IF NOT EXISTS `lp_tracks` (`name` VARCHAR(36) NOT NULL, `groups` TEXT NULL, PRIMARY KEY (`name`));";
|
||||
private static final String SQLITE_CREATETABLE_ACTION = "CREATE TABLE IF NOT EXISTS `lp_actions` (`id` INTEGER PRIMARY KEY NOT NULL, `time` BIG INT 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);";
|
||||
|
||||
private static final Map<Class<? extends SQLProvider>, String[]> INIT_QUERIES = ImmutableMap.<Class<? extends SQLProvider>, String[]>builder()
|
||||
.put(MySQLProvider.class, new String[]{MYSQL_CREATETABLE_UUID, MYSQL_CREATETABLE_USERS, MYSQL_CREATETABLE_GROUPS, MYSQL_CREATETABLE_TRACKS, MYSQL_CREATETABLE_ACTION})
|
||||
.put(H2Provider.class, new String[]{H2_CREATETABLE_UUID, H2_CREATETABLE_USERS, H2_CREATETABLE_GROUPS, H2_CREATETABLE_TRACKS, H2_CREATETABLE_ACTION})
|
||||
.put(SQLiteProvider.class, new String[]{SQLITE_CREATETABLE_UUID, SQLITE_CREATETABLE_USERS, SQLITE_CREATETABLE_GROUPS, SQLITE_CREATETABLE_TRACKS, SQLITE_CREATETABLE_ACTION})
|
||||
.build();
|
||||
|
||||
private static final String USER_INSERT = "INSERT INTO lp_users VALUES(?, ?, ?, ?)";
|
||||
private static final String USER_SELECT = "SELECT * FROM lp_users WHERE uuid=?";
|
||||
private static final String USER_SELECT_ALL = "SELECT uuid FROM lp_users";
|
||||
private static final String USER_UPDATE = "UPDATE lp_users SET name=?, primary_group = ?, perms=? WHERE uuid=?";
|
||||
private static final String USER_DELETE = "DELETE FROM lp_users WHERE uuid=?";
|
||||
private static final String USER_DELETE_ALL = "DELETE FROM lp_users WHERE perms=?";
|
||||
|
||||
private static final String GROUP_INSERT = "INSERT INTO lp_groups VALUES(?, ?)";
|
||||
private static final String GROUP_SELECT = "SELECT perms FROM lp_groups WHERE name=?";
|
||||
private static final String GROUP_SELECT_ALL = "SELECT * FROM lp_groups";
|
||||
private static final String GROUP_UPDATE = "UPDATE lp_groups SET perms=? WHERE name=?";
|
||||
private static final String GROUP_DELETE = "DELETE FROM lp_groups WHERE name=?";
|
||||
|
||||
private static final String TRACK_INSERT = "INSERT INTO lp_tracks VALUES(?, ?)";
|
||||
private static final String TRACK_SELECT = "SELECT groups FROM lp_tracks WHERE name=?";
|
||||
private static final String TRACK_SELECT_ALL = "SELECT * FROM lp_tracks";
|
||||
private static final String TRACK_UPDATE = "UPDATE lp_tracks SET groups=? WHERE name=?";
|
||||
private static final String TRACK_DELETE = "DELETE FROM lp_tracks WHERE name=?";
|
||||
|
||||
private static final String UUIDCACHE_INSERT = "INSERT INTO lp_uuid VALUES(?, ?)";
|
||||
private static final String UUIDCACHE_SELECT = "SELECT uuid FROM lp_uuid WHERE name=?";
|
||||
private static final String UUIDCACHE_SELECT_NAME = "SELECT name FROM lp_uuid WHERE uuid=?";
|
||||
private static final String UUIDCACHE_UPDATE = "UPDATE lp_uuid SET uuid=? WHERE name=?";
|
||||
|
||||
private static final String ACTION_INSERT = "INSERT INTO lp_actions(`time`, `actor_uuid`, `actor_name`, `type`, `acted_uuid`, `acted_name`, `action`) VALUES(?, ?, ?, ?, ?, ?, ?)";
|
||||
private static final String ACTION_SELECT_ALL = "SELECT * FROM lp_actions";
|
||||
|
||||
private final Gson gson;
|
||||
private final SQLProvider provider;
|
||||
|
||||
public SQLLegacyBacking(LuckPermsPlugin plugin, SQLProvider provider) {
|
||||
super(plugin, provider.getName());
|
||||
this.provider = provider;
|
||||
gson = new Gson();
|
||||
}
|
||||
|
||||
private boolean runQuery(String query, QueryPS queryPS) {
|
||||
return provider.runQuery(query, queryPS);
|
||||
}
|
||||
|
||||
private boolean runQuery(String query, QueryPS queryPS, QueryRS queryRS) {
|
||||
return provider.runQuery(query, queryPS, queryRS);
|
||||
}
|
||||
|
||||
private boolean runQuery(String query) {
|
||||
return provider.runQuery(query);
|
||||
}
|
||||
|
||||
private boolean runQuery(String query, QueryRS queryRS) {
|
||||
return provider.runQuery(query, queryRS);
|
||||
}
|
||||
|
||||
private boolean setupTables(String[] tableQueries) {
|
||||
boolean success = true;
|
||||
for (String q : tableQueries) {
|
||||
if (!runQuery(q)) success = false;
|
||||
}
|
||||
|
||||
return success && cleanupUsers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
try {
|
||||
provider.init();
|
||||
|
||||
if (!setupTables(INIT_QUERIES.get(provider.getClass()))) {
|
||||
plugin.getLog().severe("Error occurred whilst initialising the database.");
|
||||
shutdown();
|
||||
} else {
|
||||
setAcceptingLogins(true);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
try {
|
||||
provider.shutdown();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean logAction(LogEntry entry) {
|
||||
return runQuery(ACTION_INSERT, preparedStatement -> {
|
||||
preparedStatement.setLong(1, entry.getTimestamp());
|
||||
preparedStatement.setString(2, entry.getActor().toString());
|
||||
preparedStatement.setString(3, entry.getActorName());
|
||||
preparedStatement.setString(4, Character.toString(entry.getType()));
|
||||
preparedStatement.setString(5, entry.getActed() == null ? "null" : entry.getActed().toString());
|
||||
preparedStatement.setString(6, entry.getActedName());
|
||||
preparedStatement.setString(7, entry.getAction());
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Log getLog() {
|
||||
final Log.Builder log = Log.builder();
|
||||
boolean success = runQuery(ACTION_SELECT_ALL, resultSet -> {
|
||||
while (resultSet.next()) {
|
||||
final String actedUuid = resultSet.getString("acted_uuid");
|
||||
LogEntry e = new LogEntry(
|
||||
resultSet.getLong("time"),
|
||||
UUID.fromString(resultSet.getString("actor_uuid")),
|
||||
resultSet.getString("actor_name"),
|
||||
resultSet.getString("type").toCharArray()[0],
|
||||
actedUuid.equals("null") ? null : UUID.fromString(actedUuid),
|
||||
resultSet.getString("acted_name"),
|
||||
resultSet.getString("action")
|
||||
);
|
||||
log.add(e);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
return success ? log.build() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadUser(UUID uuid, String username) {
|
||||
User user = plugin.getUserManager().getOrMake(UserIdentifier.of(uuid, username));
|
||||
user.getIoLock().lock();
|
||||
try {
|
||||
// screw "effectively final"
|
||||
final String[] perms = new String[1];
|
||||
final String[] pg = new String[1];
|
||||
final String[] name = new String[1];
|
||||
final boolean[] exists = {false};
|
||||
|
||||
boolean s = runQuery(USER_SELECT,
|
||||
preparedStatement -> preparedStatement.setString(1, user.getUuid().toString()),
|
||||
resultSet -> {
|
||||
if (resultSet.next()) {
|
||||
// User exists.
|
||||
exists[0] = true;
|
||||
perms[0] = resultSet.getString("perms");
|
||||
pg[0] = resultSet.getString("primary_group");
|
||||
name[0] = resultSet.getString("name");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
if (!s) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (exists[0]) {
|
||||
// User exists, let's load.
|
||||
Map<String, Boolean> nodes = gson.fromJson(perms[0], NM_TYPE);
|
||||
|
||||
user.setNodes(nodes);
|
||||
user.setPrimaryGroup(pg[0]);
|
||||
|
||||
boolean save = plugin.getUserManager().giveDefaultIfNeeded(user, false);
|
||||
|
||||
if (user.getName() == null || user.getName().equalsIgnoreCase("null")) {
|
||||
user.setName(name[0]);
|
||||
} else {
|
||||
if (!name[0].equals(user.getName())) {
|
||||
save = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (save) {
|
||||
String json = gson.toJson(exportToLegacy(user.getNodes()));
|
||||
runQuery(USER_UPDATE, preparedStatement -> {
|
||||
preparedStatement.setString(1, user.getName());
|
||||
preparedStatement.setString(2, user.getPrimaryGroup());
|
||||
preparedStatement.setString(3, json);
|
||||
preparedStatement.setString(4, user.getUuid().toString());
|
||||
});
|
||||
}
|
||||
|
||||
} else {
|
||||
if (GenericUserManager.shouldSave(user)) {
|
||||
user.clearNodes();
|
||||
user.setPrimaryGroup(null);
|
||||
plugin.getUserManager().giveDefaultIfNeeded(user, false);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
} finally {
|
||||
user.getIoLock().unlock();
|
||||
user.getRefreshBuffer().requestDirectly();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveUser(User user) {
|
||||
if (!GenericUserManager.shouldSave(user)) {
|
||||
user.getIoLock().lock();
|
||||
try {
|
||||
return runQuery(USER_DELETE, preparedStatement -> {
|
||||
preparedStatement.setString(1, user.getUuid().toString());
|
||||
});
|
||||
} finally {
|
||||
user.getIoLock().unlock();
|
||||
}
|
||||
// return true above ^^^^^
|
||||
}
|
||||
|
||||
user.getIoLock().lock();
|
||||
try {
|
||||
final boolean[] exists = {false};
|
||||
boolean success = runQuery(USER_SELECT,
|
||||
preparedStatement -> preparedStatement.setString(1, user.getUuid().toString()),
|
||||
resultSet -> {
|
||||
if (resultSet.next()) {
|
||||
exists[0] = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
if (!success) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final String s = gson.toJson(exportToLegacy(user.getNodes()));
|
||||
|
||||
if (exists[0]) {
|
||||
// User exists, let's update.
|
||||
return runQuery(USER_UPDATE, preparedStatement -> {
|
||||
preparedStatement.setString(1, user.getName());
|
||||
preparedStatement.setString(2, user.getPrimaryGroup());
|
||||
preparedStatement.setString(3, s);
|
||||
preparedStatement.setString(4, user.getUuid().toString());
|
||||
});
|
||||
} else {
|
||||
// Doesn't already exist, let's insert.
|
||||
return runQuery(USER_INSERT, preparedStatement -> {
|
||||
preparedStatement.setString(1, user.getUuid().toString());
|
||||
preparedStatement.setString(2, user.getName());
|
||||
preparedStatement.setString(3, user.getPrimaryGroup());
|
||||
preparedStatement.setString(4, s);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
} finally {
|
||||
user.getIoLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean cleanupUsers() {
|
||||
return runQuery(USER_DELETE_ALL, preparedStatement -> {
|
||||
preparedStatement.setString(1, "{\"group.default\":true}");
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<UUID> getUniqueUsers() {
|
||||
Set<UUID> uuids = new HashSet<>();
|
||||
|
||||
boolean success = runQuery(USER_SELECT_ALL, resultSet -> {
|
||||
while (resultSet.next()) {
|
||||
String uuid = resultSet.getString("uuid");
|
||||
uuids.add(UUID.fromString(uuid));
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
return success ? uuids : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createAndLoadGroup(String name) {
|
||||
Group group = plugin.getGroupManager().getOrMake(name);
|
||||
group.getIoLock().lock();
|
||||
try {
|
||||
final boolean[] exists = {false};
|
||||
final String[] perms = new String[1];
|
||||
|
||||
boolean s = runQuery(GROUP_SELECT,
|
||||
preparedStatement -> preparedStatement.setString(1, group.getName()),
|
||||
resultSet -> {
|
||||
if (resultSet.next()) {
|
||||
exists[0] = true;
|
||||
perms[0] = resultSet.getString("perms");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
if (!s) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (exists[0]) {
|
||||
// Group exists, let's load.
|
||||
Map<String, Boolean> nodes = gson.fromJson(perms[0], NM_TYPE);
|
||||
group.setNodes(nodes);
|
||||
return true;
|
||||
} else {
|
||||
String json = gson.toJson(exportToLegacy(group.getNodes()));
|
||||
return runQuery(GROUP_INSERT, preparedStatement -> {
|
||||
preparedStatement.setString(1, group.getName());
|
||||
preparedStatement.setString(2, json);
|
||||
});
|
||||
}
|
||||
|
||||
} finally {
|
||||
group.getIoLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadGroup(String name) {
|
||||
Group group = plugin.getGroupManager().getOrMake(name);
|
||||
group.getIoLock().lock();
|
||||
try {
|
||||
final String[] perms = new String[1];
|
||||
boolean s = runQuery(GROUP_SELECT,
|
||||
preparedStatement -> preparedStatement.setString(1, name),
|
||||
resultSet -> {
|
||||
if (resultSet.next()) {
|
||||
perms[0] = resultSet.getString("perms");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
if (!s) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Group exists, let's load.
|
||||
Map<String, Boolean> nodes = gson.fromJson(perms[0], NM_TYPE);
|
||||
group.setNodes(nodes);
|
||||
return true;
|
||||
|
||||
} finally {
|
||||
group.getIoLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadAllGroups() {
|
||||
List<String> groups = new ArrayList<>();
|
||||
boolean b = runQuery(GROUP_SELECT_ALL, resultSet -> {
|
||||
while (resultSet.next()) {
|
||||
String name = resultSet.getString("name");
|
||||
groups.add(name);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
if (!b) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (String g : groups) {
|
||||
if (!loadGroup(g)) {
|
||||
b = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (b) {
|
||||
GroupManager gm = plugin.getGroupManager();
|
||||
gm.getAll().values().stream()
|
||||
.filter(g -> !groups.contains(g.getName()))
|
||||
.forEach(gm::unload);
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveGroup(Group group) {
|
||||
group.getIoLock().lock();
|
||||
try {
|
||||
String json = gson.toJson(exportToLegacy(group.getNodes()));
|
||||
return runQuery(GROUP_UPDATE, preparedStatement -> {
|
||||
preparedStatement.setString(1, json);
|
||||
preparedStatement.setString(2, group.getName());
|
||||
});
|
||||
} finally {
|
||||
group.getIoLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteGroup(Group group) {
|
||||
group.getIoLock().lock();
|
||||
boolean success;
|
||||
try {
|
||||
success = runQuery(GROUP_DELETE, preparedStatement -> {
|
||||
preparedStatement.setString(1, group.getName());
|
||||
});
|
||||
} finally {
|
||||
group.getIoLock().unlock();
|
||||
}
|
||||
|
||||
if (success) plugin.getGroupManager().unload(group);
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createAndLoadTrack(String name) {
|
||||
Track track = plugin.getTrackManager().getOrMake(name);
|
||||
track.getIoLock().lock();
|
||||
try {
|
||||
final boolean[] exists = {false};
|
||||
final String[] groups = new String[1];
|
||||
|
||||
boolean s = runQuery(TRACK_SELECT,
|
||||
preparedStatement -> preparedStatement.setString(1, track.getName()),
|
||||
resultSet -> {
|
||||
if (resultSet.next()) {
|
||||
exists[0] = true;
|
||||
groups[0] = resultSet.getString("groups");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
if (!s) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (exists[0]) {
|
||||
// Track exists, let's load.
|
||||
track.setGroups(gson.fromJson(groups[0], T_TYPE));
|
||||
return true;
|
||||
} else {
|
||||
String json = gson.toJson(track.getGroups());
|
||||
return runQuery(TRACK_INSERT, preparedStatement -> {
|
||||
preparedStatement.setString(1, track.getName());
|
||||
preparedStatement.setString(2, json);
|
||||
});
|
||||
}
|
||||
|
||||
} finally {
|
||||
track.getIoLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadTrack(String name) {
|
||||
Track track = plugin.getTrackManager().getOrMake(name);
|
||||
track.getIoLock().lock();
|
||||
try {
|
||||
final String[] groups = {null};
|
||||
boolean s = runQuery(TRACK_SELECT,
|
||||
preparedStatement -> preparedStatement.setString(1, name),
|
||||
resultSet -> {
|
||||
if (resultSet.next()) {
|
||||
groups[0] = resultSet.getString("groups");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
if (!s) {
|
||||
return false;
|
||||
}
|
||||
|
||||
track.setGroups(gson.fromJson(groups[0], T_TYPE));
|
||||
return true;
|
||||
|
||||
} finally {
|
||||
track.getIoLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadAllTracks() {
|
||||
List<String> tracks = new ArrayList<>();
|
||||
boolean b = runQuery(TRACK_SELECT_ALL, resultSet -> {
|
||||
while (resultSet.next()) {
|
||||
String name = resultSet.getString("name");
|
||||
tracks.add(name);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
if (!b) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (String t : tracks) {
|
||||
if (!loadTrack(t)) {
|
||||
b = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (b) {
|
||||
TrackManager tm = plugin.getTrackManager();
|
||||
tm.getAll().values().stream()
|
||||
.filter(t -> !tracks.contains(t.getName()))
|
||||
.forEach(tm::unload);
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveTrack(Track track) {
|
||||
track.getIoLock().lock();
|
||||
try {
|
||||
String s = gson.toJson(track.getGroups());
|
||||
return runQuery(TRACK_UPDATE, preparedStatement -> {
|
||||
preparedStatement.setString(1, s);
|
||||
preparedStatement.setString(2, track.getName());
|
||||
});
|
||||
} finally {
|
||||
track.getIoLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteTrack(Track track) {
|
||||
track.getIoLock().lock();
|
||||
boolean success;
|
||||
try {
|
||||
success = runQuery(TRACK_DELETE, preparedStatement -> {
|
||||
preparedStatement.setString(1, track.getName());
|
||||
});
|
||||
} finally {
|
||||
track.getIoLock().unlock();
|
||||
}
|
||||
|
||||
if (success) plugin.getTrackManager().unload(track);
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveUUIDData(String username, UUID uuid) {
|
||||
final String u = username.toLowerCase();
|
||||
final boolean[] update = {false};
|
||||
boolean s = runQuery(UUIDCACHE_SELECT,
|
||||
preparedStatement -> preparedStatement.setString(1, u),
|
||||
resultSet -> {
|
||||
if (resultSet.next()) {
|
||||
update[0] = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
if (!s) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (update[0]) {
|
||||
return runQuery(UUIDCACHE_UPDATE, preparedStatement -> {
|
||||
preparedStatement.setString(1, uuid.toString());
|
||||
preparedStatement.setString(2, u);
|
||||
});
|
||||
} else {
|
||||
return runQuery(UUIDCACHE_INSERT, preparedStatement -> {
|
||||
preparedStatement.setString(1, u);
|
||||
preparedStatement.setString(2, uuid.toString());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID(String username) {
|
||||
final String u = username.toLowerCase();
|
||||
final UUID[] uuid = {null};
|
||||
|
||||
boolean success = runQuery(UUIDCACHE_SELECT,
|
||||
preparedStatement -> preparedStatement.setString(1, u),
|
||||
resultSet -> {
|
||||
if (resultSet.next()) {
|
||||
uuid[0] = UUID.fromString(resultSet.getString("uuid"));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
return success ? uuid[0] : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName(UUID uuid) {
|
||||
final String u = uuid.toString();
|
||||
final String[] name = {null};
|
||||
|
||||
boolean success = runQuery(UUIDCACHE_SELECT_NAME,
|
||||
preparedStatement -> preparedStatement.setString(1, u),
|
||||
resultSet -> {
|
||||
if (resultSet.next()) {
|
||||
name[0] = resultSet.getString("name");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
return success ? name[0] : null;
|
||||
}
|
||||
}
|
@ -77,6 +77,7 @@ public class MySQLProvider extends SQLProvider {
|
||||
config.setConnectionTimeout(TimeUnit.SECONDS.toMillis(10)); // 10000
|
||||
config.setLeakDetectionThreshold(TimeUnit.SECONDS.toMillis(5)); // 5000
|
||||
config.setValidationTimeout(TimeUnit.SECONDS.toMillis(3)); // 3000
|
||||
config.setInitializationFailFast(true);
|
||||
config.setConnectionTestQuery("/* LuckPerms ping */ SELECT 1");
|
||||
|
||||
hikari = new HikariDataSource(config);
|
||||
|
@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.storage.backing.sqlprovider;
|
||||
|
||||
import com.zaxxer.hikari.HikariConfig;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
|
||||
import me.lucko.luckperms.common.storage.DatastoreConfiguration;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class PostgreSQLProvider extends SQLProvider {
|
||||
|
||||
private final DatastoreConfiguration configuration;
|
||||
private HikariDataSource hikari;
|
||||
|
||||
public PostgreSQLProvider(DatastoreConfiguration configuration) {
|
||||
super("PostgreSQL");
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() throws Exception {
|
||||
HikariConfig config = new HikariConfig();
|
||||
|
||||
String address = configuration.getAddress();
|
||||
String[] addressSplit = address.split(":");
|
||||
address = addressSplit[0];
|
||||
String port = addressSplit.length > 1 ? addressSplit[1] : "3306";
|
||||
|
||||
String database = configuration.getDatabase();
|
||||
String username = configuration.getUsername();
|
||||
String password = configuration.getPassword();
|
||||
|
||||
config.setMaximumPoolSize(configuration.getPoolSize());
|
||||
|
||||
config.setPoolName("luckperms");
|
||||
config.setDataSourceClassName("org.postgresql.ds.PGSimpleDataSource");
|
||||
config.addDataSourceProperty("serverName", address);
|
||||
config.addDataSourceProperty("portNumber", port);
|
||||
config.addDataSourceProperty("databaseName", database);
|
||||
config.addDataSourceProperty("user", username);
|
||||
config.addDataSourceProperty("password", password);
|
||||
config.setConnectionTimeout(TimeUnit.SECONDS.toMillis(10)); // 10000
|
||||
config.setLeakDetectionThreshold(TimeUnit.SECONDS.toMillis(5)); // 5000
|
||||
config.setValidationTimeout(TimeUnit.SECONDS.toMillis(3)); // 3000
|
||||
config.setInitializationFailFast(true);
|
||||
config.setConnectionTestQuery("/* LuckPerms ping */ SELECT 1");
|
||||
|
||||
hikari = new HikariDataSource(config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() throws Exception {
|
||||
if (hikari != null) {
|
||||
hikari.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection getConnection() throws SQLException {
|
||||
return hikari.getConnection();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean runQuery(String query, QueryPS queryPS) {
|
||||
boolean success = false;
|
||||
|
||||
Connection connection = null;
|
||||
PreparedStatement preparedStatement = null;
|
||||
|
||||
try {
|
||||
connection = getConnection();
|
||||
if (connection == null || connection.isClosed()) {
|
||||
throw new IllegalStateException("SQL connection is null");
|
||||
}
|
||||
|
||||
preparedStatement = connection.prepareStatement(query);
|
||||
queryPS.onRun(preparedStatement);
|
||||
|
||||
preparedStatement.execute();
|
||||
success = true;
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
close(preparedStatement);
|
||||
close(connection);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean runQuery(String query, QueryPS queryPS, QueryRS queryRS) {
|
||||
boolean success = false;
|
||||
|
||||
Connection connection = null;
|
||||
PreparedStatement preparedStatement = null;
|
||||
ResultSet resultSet = null;
|
||||
|
||||
try {
|
||||
connection = getConnection();
|
||||
if (connection == null || connection.isClosed()) {
|
||||
throw new IllegalStateException("SQL connection is null");
|
||||
}
|
||||
|
||||
preparedStatement = connection.prepareStatement(query);
|
||||
queryPS.onRun(preparedStatement);
|
||||
|
||||
resultSet = preparedStatement.executeQuery();
|
||||
success = queryRS.onResult(resultSet);
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
close(resultSet);
|
||||
close(preparedStatement);
|
||||
close(connection);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
}
|
@ -64,7 +64,6 @@ public abstract class SQLProvider {
|
||||
return runQuery(query, EMPTY_PS, queryRS);
|
||||
}
|
||||
|
||||
|
||||
@FunctionalInterface
|
||||
public interface QueryPS {
|
||||
void onRun(PreparedStatement preparedStatement) throws SQLException;
|
||||
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.storage.backing.utils;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
|
||||
import me.lucko.luckperms.api.Node;
|
||||
|
||||
@Getter
|
||||
@ToString
|
||||
@AllArgsConstructor(staticName = "of")
|
||||
public class NodeDataHolder {
|
||||
public static NodeDataHolder fromNode(Node node) {
|
||||
// TODO
|
||||
return null;
|
||||
}
|
||||
|
||||
private final String permission;
|
||||
private final boolean value;
|
||||
private final String server;
|
||||
private final String world;
|
||||
private final long expiry;
|
||||
private final String contexts;
|
||||
|
||||
public Node toNode() {
|
||||
// TODO
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
55
common/src/main/resources/sql/lp-schema-h2.sql
Normal file
55
common/src/main/resources/sql/lp-schema-h2.sql
Normal file
@ -0,0 +1,55 @@
|
||||
-- LuckPerms H2 Schema.
|
||||
|
||||
CREATE TABLE '{prefix}user_permissions' (
|
||||
'id' INT AUTO_INCREMENT NOT NULL,
|
||||
'uuid' VARCHAR(36) NOT NULL,
|
||||
'permission' VARCHAR(200) NOT NULL,
|
||||
'value' BOOL NOT NULL,
|
||||
'server' VARCHAR(36) NULL,
|
||||
'world' VARCHAR(36) NULL,
|
||||
'expiry' INT(11) NOT NULL,
|
||||
'contexts' VARCHAR(200) NULL,
|
||||
PRIMARY KEY ('id')
|
||||
);
|
||||
CREATE INDEX ON '{prefix}user_permissions' ('uuid');
|
||||
CREATE INDEX ON '{prefix}user_permissions' ('permission');
|
||||
|
||||
CREATE TABLE '{prefix}group_permissions' (
|
||||
'id' INT AUTO_INCREMENT NOT NULL,
|
||||
'name' VARCHAR(36) NOT NULL,
|
||||
'permission' VARCHAR(200) NOT NULL,
|
||||
'value' BOOL NOT NULL,
|
||||
'server' VARCHAR(36) NOT NULL,
|
||||
'world' VARCHAR(36) NOT NULL,
|
||||
'expiry' INT(11) NOT NULL,
|
||||
'contexts' VARCHAR(200) NOT NULL,
|
||||
PRIMARY KEY ('id')
|
||||
);
|
||||
CREATE INDEX ON '{prefix}group_permissions' ('name');
|
||||
CREATE INDEX ON '{prefix}group_permissions' ('permission');
|
||||
|
||||
CREATE TABLE `{prefix}players` (
|
||||
`uuid` VARCHAR(36) NOT NULL,
|
||||
`username` VARCHAR(16) NOT NULL,
|
||||
`primary_group` VARCHAR(36) NOT NULL,
|
||||
PRIMARY KEY (`uuid`)
|
||||
);
|
||||
CREATE INDEX ON '{prefix}players' ('username');
|
||||
|
||||
CREATE TABLE `{prefix}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`)
|
||||
);
|
||||
|
||||
CREATE TABLE `{prefix}tracks` (
|
||||
`name` VARCHAR(36) NOT NULL,
|
||||
`groups` TEXT NOT NULL,
|
||||
PRIMARY KEY (`name`)
|
||||
);
|
61
common/src/main/resources/sql/lp-schema-mysql.sql
Normal file
61
common/src/main/resources/sql/lp-schema-mysql.sql
Normal file
@ -0,0 +1,61 @@
|
||||
-- LuckPerms MySQL Schema
|
||||
|
||||
CREATE TABLE '{prefix}user_permissions' (
|
||||
'id' INT AUTO_INCREMENT NOT NULL,
|
||||
'uuid' VARCHAR(36) NOT NULL,
|
||||
'permission' VARCHAR(200) NOT NULL,
|
||||
'value' BOOL NOT NULL,
|
||||
'server' VARCHAR(36) NOT NULL,
|
||||
'world' VARCHAR(36) NOT NULL,
|
||||
'expiry' INT(11) NOT NULL,
|
||||
'contexts' VARCHAR(200) NOT NULL,
|
||||
PRIMARY KEY ('id')
|
||||
) DEFAULT CHARSET = utf8;
|
||||
CREATE INDEX '{prefix}user_permissions_uuid' ON '{prefix}user_permissions' ('uuid');
|
||||
CREATE INDEX '{prefix}user_permissions_permission' ON '{prefix}user_permissions' ('permission');
|
||||
|
||||
CREATE TABLE '{prefix}group_permissions' (
|
||||
'id' INT AUTO_INCREMENT NOT NULL,
|
||||
'name' VARCHAR(36) NOT NULL,
|
||||
'permission' VARCHAR(200) NOT NULL,
|
||||
'value' BOOL NOT NULL,
|
||||
'server' VARCHAR(36) NULL,
|
||||
'world' VARCHAR(36) NULL,
|
||||
'expiry' INT(11) NOT NULL,
|
||||
'contexts' VARCHAR(200) NULL,
|
||||
PRIMARY KEY ('id')
|
||||
) DEFAULT CHARSET = utf8;
|
||||
CREATE INDEX '{prefix}group_permissions_name' ON '{prefix}group_permissions' ('name');
|
||||
CREATE INDEX '{prefix}group_permissions_permission' ON '{prefix}group_permissions' ('permission');
|
||||
|
||||
CREATE TABLE `{prefix}players` (
|
||||
`uuid` VARCHAR(36) NOT NULL,
|
||||
`username` VARCHAR(16) NOT NULL,
|
||||
`primary_group` VARCHAR(36) NOT NULL,
|
||||
PRIMARY KEY (`uuid`)
|
||||
) DEFAULT CHARSET = utf8;
|
||||
CREATE INDEX '{prefix}players_username' ON '{prefix}players' ('username');
|
||||
|
||||
CREATE TABLE `{prefix}groups` (
|
||||
`id` INT AUTO_INCREMENT NOT NULL,
|
||||
`name` VARCHAR(36) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
|
||||
CREATE TABLE `{prefix}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;
|
||||
|
||||
CREATE TABLE `{prefix}tracks` (
|
||||
`name` VARCHAR(36) NOT NULL,
|
||||
`groups` TEXT NOT NULL,
|
||||
PRIMARY KEY (`name`)
|
||||
) DEFAULT CHARSET = utf8;
|
50
common/src/main/resources/sql/lp-schema-postgresql.sql
Normal file
50
common/src/main/resources/sql/lp-schema-postgresql.sql
Normal file
@ -0,0 +1,50 @@
|
||||
-- LuckPerms PostgreSQL Schema
|
||||
|
||||
CREATE TABLE "{prefix}user_permissions" (
|
||||
"id" SERIAL PRIMARY KEY NOT NULL,
|
||||
"uuid" VARCHAR(36) NOT NULL,
|
||||
"permission" VARCHAR(200) NOT NULL,
|
||||
"value" BOOL NOT NULL,
|
||||
"server" VARCHAR(36) NOT NULL,
|
||||
"world" VARCHAR(36) NOT NULL,
|
||||
"expiry" INT NOT NULL,
|
||||
"contexts" VARCHAR(200) NOT NULL
|
||||
);
|
||||
CREATE INDEX "{prefix}user_permissions_uuid" ON "{prefix}user_permissions" ("uuid");
|
||||
CREATE INDEX "{prefix}user_permissions_permission" ON "{prefix}user_permissions" ("permission");
|
||||
|
||||
CREATE TABLE "{prefix}group_permissions" (
|
||||
"id" SERIAL PRIMARY KEY NOT NULL,
|
||||
"name" VARCHAR(36) NOT NULL,
|
||||
"permission" VARCHAR(200) NOT NULL,
|
||||
"value" BOOL NOT NULL,
|
||||
"server" VARCHAR(36) NULL,
|
||||
"world" VARCHAR(36) NULL,
|
||||
"expiry" INT NOT NULL,
|
||||
"contexts" VARCHAR(200) NULL
|
||||
);
|
||||
CREATE INDEX "{prefix}group_permissions_name" ON "{prefix}group_permissions" ("name");
|
||||
CREATE INDEX "{prefix}group_permissions_permission" ON "{prefix}group_permissions" ("permission");
|
||||
|
||||
CREATE TABLE "{prefix}players" (
|
||||
"uuid" VARCHAR(36) PRIMARY KEY NOT NULL,
|
||||
"username" VARCHAR(16) NOT NULL,
|
||||
"primary_group" VARCHAR(36) NOT NULL
|
||||
);
|
||||
CREATE INDEX "{prefix}players_username" ON "{prefix}players" ("username");
|
||||
|
||||
CREATE TABLE "{prefix}actions" (
|
||||
"id" SERIAL PRIMARY KEY 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
|
||||
);
|
||||
|
||||
CREATE TABLE "{prefix}tracks" (
|
||||
"name" VARCHAR(36) PRIMARY KEY NOT NULL,
|
||||
"groups" TEXT NOT NULL
|
||||
);
|
54
common/src/main/resources/sql/lp-schema-sqlite.sql
Normal file
54
common/src/main/resources/sql/lp-schema-sqlite.sql
Normal file
@ -0,0 +1,54 @@
|
||||
-- LuckPerms SQLite Schema
|
||||
|
||||
CREATE TABLE '{prefix}user_permissions' (
|
||||
'id' INTEGER PRIMARY KEY NOT NULL,
|
||||
'uuid' VARCHAR(36) NOT NULL,
|
||||
'permission' VARCHAR(200) NOT NULL,
|
||||
'value' BOOL NOT NULL,
|
||||
'server' VARCHAR(36) NOT NULL,
|
||||
'world' VARCHAR(36) NOT NULL,
|
||||
'expiry' INT(11) NOT NULL,
|
||||
'contexts' VARCHAR(200) NOT NULL,
|
||||
PRIMARY KEY ('id')
|
||||
);
|
||||
CREATE INDEX '{prefix}user_permissions_uuid' ON '{prefix}user_permissions' ('uuid');
|
||||
CREATE INDEX '{prefix}user_permissions_permission' ON '{prefix}user_permissions' ('permission');
|
||||
|
||||
CREATE TABLE '{prefix}group_permissions' (
|
||||
'id' INTEGER PRIMARY KEY NOT NULL,
|
||||
'name' VARCHAR(36) NOT NULL,
|
||||
'permission' VARCHAR(200) NOT NULL,
|
||||
'value' BOOL NOT NULL,
|
||||
'server' VARCHAR(36) NULL,
|
||||
'world' VARCHAR(36) NULL,
|
||||
'expiry' INT(11) NOT NULL,
|
||||
'contexts' VARCHAR(200) NULL,
|
||||
PRIMARY KEY ('id')
|
||||
);
|
||||
CREATE INDEX '{prefix}group_permissions_name' ON '{prefix}group_permissions' ('name');
|
||||
CREATE INDEX '{prefix}group_permissions_permission' ON '{prefix}group_permissions' ('permission');
|
||||
|
||||
CREATE TABLE `{prefix}players` (
|
||||
`uuid` VARCHAR(36) NOT NULL,
|
||||
`username` VARCHAR(16) NOT NULL,
|
||||
`primary_group` VARCHAR(36) NOT NULL,
|
||||
PRIMARY KEY (`uuid`)
|
||||
);
|
||||
CREATE INDEX '{prefix}players_username' ON '{prefix}players' ('username');
|
||||
|
||||
CREATE TABLE `{prefix}actions` (
|
||||
`id` INTEGER PRIMARY KEY 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
|
||||
);
|
||||
|
||||
CREATE TABLE `{prefix}tracks` (
|
||||
`name` VARCHAR(36) NOT NULL,
|
||||
`groups` TEXT NOT NULL,
|
||||
PRIMARY KEY (`name`)
|
||||
);
|
Loading…
Reference in New Issue
Block a user