mirror of
https://github.com/LuckPerms/LuckPerms.git
synced 2024-10-02 23:37:29 +02:00
Add YAML storage support
This commit is contained in:
parent
5c760aabd4
commit
5dec5a54cb
@ -43,7 +43,7 @@ apply-shorthand: true
|
|||||||
log-notify: true
|
log-notify: true
|
||||||
|
|
||||||
# Which storage method the plugin should use.
|
# Which storage method the plugin should use.
|
||||||
# Currently supported: mysql, sqlite, h2, flatfile, mongodb
|
# Currently supported: mysql, sqlite, h2, json, yaml, mongodb
|
||||||
# Fill out connection info below if you're using MySQL or MongoDB
|
# Fill out connection info below if you're using MySQL or MongoDB
|
||||||
storage-method: h2
|
storage-method: h2
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ apply-shorthand: true
|
|||||||
log-notify: true
|
log-notify: true
|
||||||
|
|
||||||
# Which storage method the plugin should use.
|
# Which storage method the plugin should use.
|
||||||
# Currently supported: mysql, sqlite, h2, flatfile, mongodb
|
# Currently supported: mysql, sqlite, h2, json, yaml, mongodb
|
||||||
# Fill out connection info below if you're using MySQL or MongoDB
|
# Fill out connection info below if you're using MySQL or MongoDB
|
||||||
storage-method: h2
|
storage-method: h2
|
||||||
|
|
||||||
|
@ -67,6 +67,13 @@
|
|||||||
<version>1.7.9</version>
|
<version>1.7.9</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- SnakeYAML -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.yaml</groupId>
|
||||||
|
<artifactId>snakeyaml</artifactId>
|
||||||
|
<version>1.14</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
<!-- gson -->
|
<!-- gson -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.google.code.gson</groupId>
|
<groupId>com.google.code.gson</groupId>
|
||||||
|
@ -35,7 +35,7 @@ import java.util.Set;
|
|||||||
|
|
||||||
@UtilityClass
|
@UtilityClass
|
||||||
public class StorageFactory {
|
public class StorageFactory {
|
||||||
private static final Set<String> TYPES = ImmutableSet.of("flatfile", "mongodb", "mysql", "sqlite", "h2");
|
private static final Set<String> TYPES = ImmutableSet.of("json", "yaml", "flatfile", "mongodb", "mysql", "sqlite", "h2");
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static Datastore getDatastore(LuckPermsPlugin plugin, String defaultMethod) {
|
public static Datastore getDatastore(LuckPermsPlugin plugin, String defaultMethod) {
|
||||||
@ -93,8 +93,10 @@ public class StorageFactory {
|
|||||||
return new H2Datastore(plugin, new File(plugin.getDataFolder(), "luckperms.db"));
|
return new H2Datastore(plugin, new File(plugin.getDataFolder(), "luckperms.db"));
|
||||||
case "mongodb":
|
case "mongodb":
|
||||||
return new MongoDBDatastore(plugin, plugin.getConfiguration().getDatabaseValues());
|
return new MongoDBDatastore(plugin, plugin.getConfiguration().getDatabaseValues());
|
||||||
|
case "yaml":
|
||||||
|
return new YAMLDatastore(plugin, plugin.getDataFolder());
|
||||||
default:
|
default:
|
||||||
return new FlatfileDatastore(plugin, plugin.getDataFolder());
|
return new JSONDatastore(plugin, plugin.getDataFolder());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,75 +22,37 @@
|
|||||||
|
|
||||||
package me.lucko.luckperms.storage.methods;
|
package me.lucko.luckperms.storage.methods;
|
||||||
|
|
||||||
import com.google.gson.stream.JsonReader;
|
|
||||||
import com.google.gson.stream.JsonWriter;
|
|
||||||
import lombok.Cleanup;
|
import lombok.Cleanup;
|
||||||
import me.lucko.luckperms.LuckPermsPlugin;
|
import me.lucko.luckperms.LuckPermsPlugin;
|
||||||
import me.lucko.luckperms.api.LogEntry;
|
import me.lucko.luckperms.api.LogEntry;
|
||||||
import me.lucko.luckperms.constants.Constants;
|
import me.lucko.luckperms.constants.Constants;
|
||||||
import me.lucko.luckperms.data.Log;
|
import me.lucko.luckperms.data.Log;
|
||||||
import me.lucko.luckperms.groups.Group;
|
|
||||||
import me.lucko.luckperms.storage.Datastore;
|
import me.lucko.luckperms.storage.Datastore;
|
||||||
import me.lucko.luckperms.tracks.Track;
|
|
||||||
import me.lucko.luckperms.users.User;
|
|
||||||
import me.lucko.luckperms.utils.Node;
|
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.logging.*;
|
import java.util.logging.*;
|
||||||
import java.util.logging.Formatter;
|
import java.util.logging.Formatter;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import static me.lucko.luckperms.core.PermissionHolder.exportToLegacy;
|
abstract class FlatfileDatastore extends Datastore {
|
||||||
|
|
||||||
@SuppressWarnings({"ResultOfMethodCallIgnored", "UnnecessaryLocalVariable"})
|
|
||||||
public class FlatfileDatastore extends Datastore {
|
|
||||||
private static final String LOG_FORMAT = "%s(%s): [%s] %s(%s) --> %s";
|
private static final String LOG_FORMAT = "%s(%s): [%s] %s(%s) --> %s";
|
||||||
|
|
||||||
private final Logger actionLogger = Logger.getLogger("lp_actions");
|
private final Logger actionLogger = Logger.getLogger("lp_actions");
|
||||||
private Map<String, String> uuidCache = new ConcurrentHashMap<>();
|
private Map<String, String> uuidCache = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private final File pluginDir;
|
final File pluginDir;
|
||||||
private File usersDir;
|
File usersDir;
|
||||||
private File groupsDir;
|
File groupsDir;
|
||||||
private File tracksDir;
|
File tracksDir;
|
||||||
private File uuidData;
|
File uuidData;
|
||||||
private File actionLog;
|
File actionLog;
|
||||||
|
|
||||||
public FlatfileDatastore(LuckPermsPlugin plugin, File pluginDir) {
|
FlatfileDatastore(LuckPermsPlugin plugin, String name, File pluginDir) {
|
||||||
super(plugin, "Flatfile - JSON");
|
super(plugin, name);
|
||||||
this.pluginDir = pluginDir;
|
this.pluginDir = pluginDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean doWrite(File file, WriteOperation writeOperation) {
|
|
||||||
boolean success = false;
|
|
||||||
try {
|
|
||||||
@Cleanup FileWriter fileWriter = new FileWriter(file);
|
|
||||||
@Cleanup BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
|
|
||||||
@Cleanup JsonWriter jsonWriter = new JsonWriter(bufferedWriter);
|
|
||||||
jsonWriter.setIndent(" ");
|
|
||||||
success = writeOperation.onRun(jsonWriter);
|
|
||||||
jsonWriter.flush();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean doRead(File file, ReadOperation readOperation) {
|
|
||||||
boolean success = false;
|
|
||||||
try {
|
|
||||||
@Cleanup FileReader fileReader = new FileReader(file);
|
|
||||||
@Cleanup BufferedReader bufferedReader = new BufferedReader(fileReader);
|
|
||||||
@Cleanup JsonReader jsonReader = new JsonReader(bufferedReader);
|
|
||||||
success = readOperation.onRun(jsonReader);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init() {
|
public void init() {
|
||||||
try {
|
try {
|
||||||
@ -120,9 +82,17 @@ public class FlatfileDatastore extends Datastore {
|
|||||||
|
|
||||||
cleanupUsers();
|
cleanupUsers();
|
||||||
|
|
||||||
|
try {
|
||||||
|
childInit();
|
||||||
|
} catch (Exception e) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
setAcceptingLogins(true);
|
setAcceptingLogins(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected abstract void childInit() throws Exception;
|
||||||
|
|
||||||
private void makeFiles() throws IOException {
|
private void makeFiles() throws IOException {
|
||||||
File data = new File(pluginDir, "data");
|
File data = new File(pluginDir, "data");
|
||||||
data.mkdirs();
|
data.mkdirs();
|
||||||
@ -167,411 +137,6 @@ public class FlatfileDatastore extends Datastore {
|
|||||||
return Log.builder().build();
|
return Log.builder().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean loadUser(UUID uuid, String username) {
|
|
||||||
User user = plugin.getUserManager().make(uuid, username);
|
|
||||||
boolean success = false;
|
|
||||||
|
|
||||||
File userFile = new File(usersDir, uuid.toString() + ".json");
|
|
||||||
if (userFile.exists()) {
|
|
||||||
final String[] name = new String[1];
|
|
||||||
success = doRead(userFile, reader -> {
|
|
||||||
reader.beginObject();
|
|
||||||
reader.nextName(); // uuid record
|
|
||||||
reader.nextString(); // uuid
|
|
||||||
reader.nextName(); // name record
|
|
||||||
name[0] = reader.nextString(); // name
|
|
||||||
reader.nextName(); // primaryGroup record
|
|
||||||
user.setPrimaryGroup(reader.nextString()); // primaryGroup
|
|
||||||
reader.nextName(); //perms
|
|
||||||
reader.beginObject();
|
|
||||||
while (reader.hasNext()) {
|
|
||||||
String node = reader.nextName();
|
|
||||||
boolean b = reader.nextBoolean();
|
|
||||||
user.getNodes().add(Node.fromSerialisedNode(node, b));
|
|
||||||
}
|
|
||||||
|
|
||||||
reader.endObject();
|
|
||||||
reader.endObject();
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (user.getName().equalsIgnoreCase("null")) {
|
|
||||||
user.setName(name[0]);
|
|
||||||
} else {
|
|
||||||
if (!name[0].equals(user.getName())) {
|
|
||||||
doWrite(userFile, writer -> {
|
|
||||||
writer.beginObject();
|
|
||||||
writer.name("uuid").value(user.getUuid().toString());
|
|
||||||
writer.name("name").value(user.getName());
|
|
||||||
writer.name("primaryGroup").value(user.getPrimaryGroup());
|
|
||||||
writer.name("perms");
|
|
||||||
writer.beginObject();
|
|
||||||
for (Map.Entry<String, Boolean> e : exportToLegacy(user.getNodes()).entrySet()) {
|
|
||||||
writer.name(e.getKey()).value(e.getValue().booleanValue());
|
|
||||||
}
|
|
||||||
writer.endObject();
|
|
||||||
writer.endObject();
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
success = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (success) plugin.getUserManager().updateOrSet(user);
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean saveUser(User user) {
|
|
||||||
File userFile = new File(usersDir, user.getUuid().toString() + ".json");
|
|
||||||
if (!plugin.getUserManager().shouldSave(user)) {
|
|
||||||
if (userFile.exists()) {
|
|
||||||
userFile.delete();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!userFile.exists()) {
|
|
||||||
try {
|
|
||||||
userFile.createNewFile();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean success = doWrite(userFile, writer -> {
|
|
||||||
writer.beginObject();
|
|
||||||
writer.name("uuid").value(user.getUuid().toString());
|
|
||||||
writer.name("name").value(user.getName());
|
|
||||||
writer.name("primaryGroup").value(user.getPrimaryGroup());
|
|
||||||
writer.name("perms");
|
|
||||||
writer.beginObject();
|
|
||||||
for (Map.Entry<String, Boolean> e : exportToLegacy(user.getNodes()).entrySet()) {
|
|
||||||
writer.name(e.getKey()).value(e.getValue().booleanValue());
|
|
||||||
}
|
|
||||||
writer.endObject();
|
|
||||||
writer.endObject();
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean cleanupUsers() {
|
|
||||||
File[] files = usersDir.listFiles((dir, name) -> name.endsWith(".json"));
|
|
||||||
if (files == null) return false;
|
|
||||||
|
|
||||||
for (File file : files) {
|
|
||||||
Map<String, Boolean> nodes = new HashMap<>();
|
|
||||||
doRead(file, reader -> {
|
|
||||||
reader.beginObject();
|
|
||||||
reader.nextName(); // uuid record
|
|
||||||
reader.nextString(); // uuid
|
|
||||||
reader.nextName(); // name record
|
|
||||||
reader.nextString(); // name
|
|
||||||
reader.nextName(); // primaryGroup record
|
|
||||||
reader.nextString(); // primaryGroup
|
|
||||||
reader.nextName(); //perms
|
|
||||||
reader.beginObject();
|
|
||||||
while (reader.hasNext()) {
|
|
||||||
String node = reader.nextName();
|
|
||||||
boolean b = reader.nextBoolean();
|
|
||||||
nodes.put(node, b);
|
|
||||||
}
|
|
||||||
|
|
||||||
reader.endObject();
|
|
||||||
reader.endObject();
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
boolean shouldDelete = false;
|
|
||||||
if (nodes.size() == 1) {
|
|
||||||
for (Map.Entry<String, Boolean> e : nodes.entrySet()) {
|
|
||||||
// There's only one
|
|
||||||
shouldDelete = e.getKey().equalsIgnoreCase("group.default") && e.getValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shouldDelete) {
|
|
||||||
file.delete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<UUID> getUniqueUsers() {
|
|
||||||
String[] fileNames = usersDir.list((dir, name) -> name.endsWith(".json"));
|
|
||||||
if (fileNames == null) return null;
|
|
||||||
return Arrays.stream(fileNames)
|
|
||||||
.map(s -> s.substring(0, s.length() - 5))
|
|
||||||
.map(UUID::fromString)
|
|
||||||
.collect(Collectors.toSet());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean createAndLoadGroup(String name) {
|
|
||||||
Group group = plugin.getGroupManager().make(name);
|
|
||||||
|
|
||||||
File groupFile = new File(groupsDir, name + ".json");
|
|
||||||
if (!groupFile.exists()) {
|
|
||||||
try {
|
|
||||||
groupFile.createNewFile();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean success = doWrite(groupFile, writer -> {
|
|
||||||
writer.beginObject();
|
|
||||||
writer.name("name").value(group.getName());
|
|
||||||
writer.name("perms");
|
|
||||||
writer.beginObject();
|
|
||||||
for (Map.Entry<String, Boolean> e : exportToLegacy(group.getNodes()).entrySet()) {
|
|
||||||
writer.name(e.getKey()).value(e.getValue().booleanValue());
|
|
||||||
}
|
|
||||||
writer.endObject();
|
|
||||||
writer.endObject();
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!success) return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean success = doRead(groupFile, reader -> {
|
|
||||||
reader.beginObject();
|
|
||||||
reader.nextName(); // name record
|
|
||||||
reader.nextString(); // name
|
|
||||||
reader.nextName(); //perms
|
|
||||||
reader.beginObject();
|
|
||||||
while (reader.hasNext()) {
|
|
||||||
String node = reader.nextName();
|
|
||||||
boolean b = reader.nextBoolean();
|
|
||||||
group.getNodes().add(Node.fromSerialisedNode(node, b));
|
|
||||||
}
|
|
||||||
|
|
||||||
reader.endObject();
|
|
||||||
reader.endObject();
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (success) plugin.getGroupManager().updateOrSet(group);
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean loadGroup(String name) {
|
|
||||||
Group group = plugin.getGroupManager().make(name);
|
|
||||||
|
|
||||||
File groupFile = new File(groupsDir, name + ".json");
|
|
||||||
if (!groupFile.exists()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean success = doRead(groupFile, reader -> {
|
|
||||||
reader.beginObject();
|
|
||||||
reader.nextName(); // name record
|
|
||||||
reader.nextString(); // name
|
|
||||||
reader.nextName(); //perms
|
|
||||||
reader.beginObject();
|
|
||||||
while (reader.hasNext()) {
|
|
||||||
String node = reader.nextName();
|
|
||||||
boolean b = reader.nextBoolean();
|
|
||||||
group.getNodes().add(Node.fromSerialisedNode(node, b));
|
|
||||||
}
|
|
||||||
|
|
||||||
reader.endObject();
|
|
||||||
reader.endObject();
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (success) plugin.getGroupManager().updateOrSet(group);
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean loadAllGroups() {
|
|
||||||
String[] fileNames = groupsDir.list((dir, name) -> name.endsWith(".json"));
|
|
||||||
if (fileNames == null) return false;
|
|
||||||
List<String> groups = Arrays.stream(fileNames)
|
|
||||||
.map(s -> s.substring(0, s.length() - 5))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
|
|
||||||
plugin.getGroupManager().unloadAll();
|
|
||||||
groups.forEach(this::loadGroup);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean saveGroup(Group group) {
|
|
||||||
File groupFile = new File(groupsDir, group.getName() + ".json");
|
|
||||||
if (!groupFile.exists()) {
|
|
||||||
try {
|
|
||||||
groupFile.createNewFile();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean success = doWrite(groupFile, writer -> {
|
|
||||||
writer.beginObject();
|
|
||||||
writer.name("name").value(group.getName());
|
|
||||||
writer.name("perms");
|
|
||||||
writer.beginObject();
|
|
||||||
for (Map.Entry<String, Boolean> e : exportToLegacy(group.getNodes()).entrySet()) {
|
|
||||||
writer.name(e.getKey()).value(e.getValue().booleanValue());
|
|
||||||
}
|
|
||||||
writer.endObject();
|
|
||||||
writer.endObject();
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean deleteGroup(Group group) {
|
|
||||||
File groupFile = new File(groupsDir, group.getName() + ".json");
|
|
||||||
if (groupFile.exists()) {
|
|
||||||
groupFile.delete();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean createAndLoadTrack(String name) {
|
|
||||||
Track track = plugin.getTrackManager().make(name);
|
|
||||||
List<String> groups = new ArrayList<>();
|
|
||||||
|
|
||||||
File trackFile = new File(tracksDir, name + ".json");
|
|
||||||
if (!trackFile.exists()) {
|
|
||||||
try {
|
|
||||||
trackFile.createNewFile();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean success = doWrite(trackFile, writer -> {
|
|
||||||
writer.beginObject();
|
|
||||||
writer.name("name").value(track.getName());
|
|
||||||
writer.name("groups");
|
|
||||||
writer.beginArray();
|
|
||||||
for (String s : track.getGroups()) {
|
|
||||||
writer.value(s);
|
|
||||||
}
|
|
||||||
writer.endArray();
|
|
||||||
writer.endObject();
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!success) return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean success = doRead(trackFile, reader -> {
|
|
||||||
reader.beginObject();
|
|
||||||
reader.nextName(); // name record
|
|
||||||
reader.nextString(); // name
|
|
||||||
reader.nextName(); // groups record
|
|
||||||
reader.beginArray();
|
|
||||||
while (reader.hasNext()) {
|
|
||||||
groups.add(reader.nextString());
|
|
||||||
}
|
|
||||||
reader.endArray();
|
|
||||||
reader.endObject();
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
track.setGroups(groups);
|
|
||||||
if (success) plugin.getTrackManager().updateOrSet(track);
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean loadTrack(String name) {
|
|
||||||
Track track = plugin.getTrackManager().make(name);
|
|
||||||
List<String> groups = new ArrayList<>();
|
|
||||||
|
|
||||||
File trackFile = new File(tracksDir, name + ".json");
|
|
||||||
if (!trackFile.exists()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean success = doRead(trackFile, reader -> {
|
|
||||||
reader.beginObject();
|
|
||||||
reader.nextName(); // name record
|
|
||||||
reader.nextString(); // name
|
|
||||||
reader.nextName(); // groups record
|
|
||||||
reader.beginArray();
|
|
||||||
while (reader.hasNext()) {
|
|
||||||
groups.add(reader.nextString());
|
|
||||||
}
|
|
||||||
reader.endArray();
|
|
||||||
reader.endObject();
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
track.setGroups(groups);
|
|
||||||
if (success) plugin.getTrackManager().updateOrSet(track);
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean loadAllTracks() {
|
|
||||||
String[] fileNames = tracksDir.list((dir, name) -> name.endsWith(".json"));
|
|
||||||
if (fileNames == null) return false;
|
|
||||||
List<String> tracks = Arrays.stream(fileNames)
|
|
||||||
.map(s -> s.substring(0, s.length() - 5))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
|
|
||||||
plugin.getTrackManager().unloadAll();
|
|
||||||
tracks.forEach(this::loadTrack);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean saveTrack(Track track) {
|
|
||||||
File trackFile = new File(tracksDir, track.getName() + ".json");
|
|
||||||
if (!trackFile.exists()) {
|
|
||||||
try {
|
|
||||||
trackFile.createNewFile();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean success = doWrite(trackFile, writer -> {
|
|
||||||
writer.beginObject();
|
|
||||||
writer.name("name").value(track.getName());
|
|
||||||
writer.name("groups");
|
|
||||||
writer.beginArray();
|
|
||||||
for (String s : track.getGroups()) {
|
|
||||||
writer.value(s);
|
|
||||||
}
|
|
||||||
writer.endArray();
|
|
||||||
writer.endObject();
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean deleteTrack(Track track) {
|
|
||||||
File trackFile = new File(tracksDir, track.getName() + ".json");
|
|
||||||
if (trackFile.exists()) {
|
|
||||||
trackFile.delete();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Map<String, String> getUUIDCache() {
|
private Map<String, String> getUUIDCache() {
|
||||||
Map<String, String> cache = new HashMap<>();
|
Map<String, String> cache = new HashMap<>();
|
||||||
|
|
||||||
@ -628,12 +193,4 @@ public class FlatfileDatastore extends Datastore {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface WriteOperation {
|
|
||||||
boolean onRun(JsonWriter writer) throws IOException;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ReadOperation {
|
|
||||||
boolean onRun(JsonReader reader) throws IOException;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,498 @@
|
|||||||
|
/*
|
||||||
|
* 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.google.gson.stream.JsonReader;
|
||||||
|
import com.google.gson.stream.JsonWriter;
|
||||||
|
import lombok.Cleanup;
|
||||||
|
import me.lucko.luckperms.LuckPermsPlugin;
|
||||||
|
import me.lucko.luckperms.api.LogEntry;
|
||||||
|
import me.lucko.luckperms.constants.Constants;
|
||||||
|
import me.lucko.luckperms.data.Log;
|
||||||
|
import me.lucko.luckperms.groups.Group;
|
||||||
|
import me.lucko.luckperms.storage.Datastore;
|
||||||
|
import me.lucko.luckperms.tracks.Track;
|
||||||
|
import me.lucko.luckperms.users.User;
|
||||||
|
import me.lucko.luckperms.utils.Node;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.logging.*;
|
||||||
|
import java.util.logging.Formatter;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static me.lucko.luckperms.core.PermissionHolder.exportToLegacy;
|
||||||
|
|
||||||
|
@SuppressWarnings({"ResultOfMethodCallIgnored", "UnnecessaryLocalVariable"})
|
||||||
|
public class JSONDatastore extends FlatfileDatastore {
|
||||||
|
public JSONDatastore(LuckPermsPlugin plugin, File pluginDir) {
|
||||||
|
super(plugin, "Flatfile - JSON", pluginDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean doWrite(File file, WriteOperation writeOperation) {
|
||||||
|
boolean success = false;
|
||||||
|
try {
|
||||||
|
@Cleanup FileWriter fileWriter = new FileWriter(file);
|
||||||
|
@Cleanup BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
|
||||||
|
@Cleanup JsonWriter jsonWriter = new JsonWriter(bufferedWriter);
|
||||||
|
jsonWriter.setIndent(" ");
|
||||||
|
success = writeOperation.onRun(jsonWriter);
|
||||||
|
jsonWriter.flush();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean doRead(File file, ReadOperation readOperation) {
|
||||||
|
boolean success = false;
|
||||||
|
try {
|
||||||
|
@Cleanup FileReader fileReader = new FileReader(file);
|
||||||
|
@Cleanup BufferedReader bufferedReader = new BufferedReader(fileReader);
|
||||||
|
@Cleanup JsonReader jsonReader = new JsonReader(bufferedReader);
|
||||||
|
success = readOperation.onRun(jsonReader);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void childInit() throws Exception {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean loadUser(UUID uuid, String username) {
|
||||||
|
User user = plugin.getUserManager().make(uuid, username);
|
||||||
|
boolean success = false;
|
||||||
|
|
||||||
|
File userFile = new File(usersDir, uuid.toString() + ".json");
|
||||||
|
if (userFile.exists()) {
|
||||||
|
final String[] name = new String[1];
|
||||||
|
success = doRead(userFile, reader -> {
|
||||||
|
reader.beginObject();
|
||||||
|
reader.nextName(); // uuid record
|
||||||
|
reader.nextString(); // uuid
|
||||||
|
reader.nextName(); // name record
|
||||||
|
name[0] = reader.nextString(); // name
|
||||||
|
reader.nextName(); // primaryGroup record
|
||||||
|
user.setPrimaryGroup(reader.nextString()); // primaryGroup
|
||||||
|
reader.nextName(); //perms
|
||||||
|
reader.beginObject();
|
||||||
|
while (reader.hasNext()) {
|
||||||
|
String node = reader.nextName();
|
||||||
|
boolean b = reader.nextBoolean();
|
||||||
|
user.getNodes().add(Node.fromSerialisedNode(node, b));
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.endObject();
|
||||||
|
reader.endObject();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (user.getName().equalsIgnoreCase("null")) {
|
||||||
|
user.setName(name[0]);
|
||||||
|
} else {
|
||||||
|
if (!name[0].equals(user.getName())) {
|
||||||
|
doWrite(userFile, writer -> {
|
||||||
|
writer.beginObject();
|
||||||
|
writer.name("uuid").value(user.getUuid().toString());
|
||||||
|
writer.name("name").value(user.getName());
|
||||||
|
writer.name("primaryGroup").value(user.getPrimaryGroup());
|
||||||
|
writer.name("perms");
|
||||||
|
writer.beginObject();
|
||||||
|
for (Map.Entry<String, Boolean> e : exportToLegacy(user.getNodes()).entrySet()) {
|
||||||
|
writer.name(e.getKey()).value(e.getValue().booleanValue());
|
||||||
|
}
|
||||||
|
writer.endObject();
|
||||||
|
writer.endObject();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success) plugin.getUserManager().updateOrSet(user);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean saveUser(User user) {
|
||||||
|
File userFile = new File(usersDir, user.getUuid().toString() + ".json");
|
||||||
|
if (!plugin.getUserManager().shouldSave(user)) {
|
||||||
|
if (userFile.exists()) {
|
||||||
|
userFile.delete();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!userFile.exists()) {
|
||||||
|
try {
|
||||||
|
userFile.createNewFile();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean success = doWrite(userFile, writer -> {
|
||||||
|
writer.beginObject();
|
||||||
|
writer.name("uuid").value(user.getUuid().toString());
|
||||||
|
writer.name("name").value(user.getName());
|
||||||
|
writer.name("primaryGroup").value(user.getPrimaryGroup());
|
||||||
|
writer.name("perms");
|
||||||
|
writer.beginObject();
|
||||||
|
for (Map.Entry<String, Boolean> e : exportToLegacy(user.getNodes()).entrySet()) {
|
||||||
|
writer.name(e.getKey()).value(e.getValue().booleanValue());
|
||||||
|
}
|
||||||
|
writer.endObject();
|
||||||
|
writer.endObject();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean cleanupUsers() {
|
||||||
|
File[] files = usersDir.listFiles((dir, name) -> name.endsWith(".json"));
|
||||||
|
if (files == null) return false;
|
||||||
|
|
||||||
|
for (File file : files) {
|
||||||
|
Map<String, Boolean> nodes = new HashMap<>();
|
||||||
|
doRead(file, reader -> {
|
||||||
|
reader.beginObject();
|
||||||
|
reader.nextName(); // uuid record
|
||||||
|
reader.nextString(); // uuid
|
||||||
|
reader.nextName(); // name record
|
||||||
|
reader.nextString(); // name
|
||||||
|
reader.nextName(); // primaryGroup record
|
||||||
|
reader.nextString(); // primaryGroup
|
||||||
|
reader.nextName(); //perms
|
||||||
|
reader.beginObject();
|
||||||
|
while (reader.hasNext()) {
|
||||||
|
String node = reader.nextName();
|
||||||
|
boolean b = reader.nextBoolean();
|
||||||
|
nodes.put(node, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.endObject();
|
||||||
|
reader.endObject();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
boolean shouldDelete = false;
|
||||||
|
if (nodes.size() == 1) {
|
||||||
|
for (Map.Entry<String, Boolean> e : nodes.entrySet()) {
|
||||||
|
// There's only one
|
||||||
|
shouldDelete = e.getKey().equalsIgnoreCase("group.default") && e.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldDelete) {
|
||||||
|
file.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<UUID> getUniqueUsers() {
|
||||||
|
String[] fileNames = usersDir.list((dir, name) -> name.endsWith(".json"));
|
||||||
|
if (fileNames == null) return null;
|
||||||
|
return Arrays.stream(fileNames)
|
||||||
|
.map(s -> s.substring(0, s.length() - 5))
|
||||||
|
.map(UUID::fromString)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean createAndLoadGroup(String name) {
|
||||||
|
Group group = plugin.getGroupManager().make(name);
|
||||||
|
|
||||||
|
File groupFile = new File(groupsDir, name + ".json");
|
||||||
|
if (!groupFile.exists()) {
|
||||||
|
try {
|
||||||
|
groupFile.createNewFile();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean success = doWrite(groupFile, writer -> {
|
||||||
|
writer.beginObject();
|
||||||
|
writer.name("name").value(group.getName());
|
||||||
|
writer.name("perms");
|
||||||
|
writer.beginObject();
|
||||||
|
for (Map.Entry<String, Boolean> e : exportToLegacy(group.getNodes()).entrySet()) {
|
||||||
|
writer.name(e.getKey()).value(e.getValue().booleanValue());
|
||||||
|
}
|
||||||
|
writer.endObject();
|
||||||
|
writer.endObject();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!success) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean success = doRead(groupFile, reader -> {
|
||||||
|
reader.beginObject();
|
||||||
|
reader.nextName(); // name record
|
||||||
|
reader.nextString(); // name
|
||||||
|
reader.nextName(); //perms
|
||||||
|
reader.beginObject();
|
||||||
|
while (reader.hasNext()) {
|
||||||
|
String node = reader.nextName();
|
||||||
|
boolean b = reader.nextBoolean();
|
||||||
|
group.getNodes().add(Node.fromSerialisedNode(node, b));
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.endObject();
|
||||||
|
reader.endObject();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (success) plugin.getGroupManager().updateOrSet(group);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean loadGroup(String name) {
|
||||||
|
Group group = plugin.getGroupManager().make(name);
|
||||||
|
|
||||||
|
File groupFile = new File(groupsDir, name + ".json");
|
||||||
|
if (!groupFile.exists()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean success = doRead(groupFile, reader -> {
|
||||||
|
reader.beginObject();
|
||||||
|
reader.nextName(); // name record
|
||||||
|
reader.nextString(); // name
|
||||||
|
reader.nextName(); //perms
|
||||||
|
reader.beginObject();
|
||||||
|
while (reader.hasNext()) {
|
||||||
|
String node = reader.nextName();
|
||||||
|
boolean b = reader.nextBoolean();
|
||||||
|
group.getNodes().add(Node.fromSerialisedNode(node, b));
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.endObject();
|
||||||
|
reader.endObject();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (success) plugin.getGroupManager().updateOrSet(group);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean loadAllGroups() {
|
||||||
|
String[] fileNames = groupsDir.list((dir, name) -> name.endsWith(".json"));
|
||||||
|
if (fileNames == null) return false;
|
||||||
|
List<String> groups = Arrays.stream(fileNames)
|
||||||
|
.map(s -> s.substring(0, s.length() - 5))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
plugin.getGroupManager().unloadAll();
|
||||||
|
groups.forEach(this::loadGroup);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean saveGroup(Group group) {
|
||||||
|
File groupFile = new File(groupsDir, group.getName() + ".json");
|
||||||
|
if (!groupFile.exists()) {
|
||||||
|
try {
|
||||||
|
groupFile.createNewFile();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean success = doWrite(groupFile, writer -> {
|
||||||
|
writer.beginObject();
|
||||||
|
writer.name("name").value(group.getName());
|
||||||
|
writer.name("perms");
|
||||||
|
writer.beginObject();
|
||||||
|
for (Map.Entry<String, Boolean> e : exportToLegacy(group.getNodes()).entrySet()) {
|
||||||
|
writer.name(e.getKey()).value(e.getValue().booleanValue());
|
||||||
|
}
|
||||||
|
writer.endObject();
|
||||||
|
writer.endObject();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean deleteGroup(Group group) {
|
||||||
|
File groupFile = new File(groupsDir, group.getName() + ".json");
|
||||||
|
if (groupFile.exists()) {
|
||||||
|
groupFile.delete();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean createAndLoadTrack(String name) {
|
||||||
|
Track track = plugin.getTrackManager().make(name);
|
||||||
|
List<String> groups = new ArrayList<>();
|
||||||
|
|
||||||
|
File trackFile = new File(tracksDir, name + ".json");
|
||||||
|
if (!trackFile.exists()) {
|
||||||
|
try {
|
||||||
|
trackFile.createNewFile();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean success = doWrite(trackFile, writer -> {
|
||||||
|
writer.beginObject();
|
||||||
|
writer.name("name").value(track.getName());
|
||||||
|
writer.name("groups");
|
||||||
|
writer.beginArray();
|
||||||
|
for (String s : track.getGroups()) {
|
||||||
|
writer.value(s);
|
||||||
|
}
|
||||||
|
writer.endArray();
|
||||||
|
writer.endObject();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!success) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean success = doRead(trackFile, reader -> {
|
||||||
|
reader.beginObject();
|
||||||
|
reader.nextName(); // name record
|
||||||
|
reader.nextString(); // name
|
||||||
|
reader.nextName(); // groups record
|
||||||
|
reader.beginArray();
|
||||||
|
while (reader.hasNext()) {
|
||||||
|
groups.add(reader.nextString());
|
||||||
|
}
|
||||||
|
reader.endArray();
|
||||||
|
reader.endObject();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
track.setGroups(groups);
|
||||||
|
if (success) plugin.getTrackManager().updateOrSet(track);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean loadTrack(String name) {
|
||||||
|
Track track = plugin.getTrackManager().make(name);
|
||||||
|
List<String> groups = new ArrayList<>();
|
||||||
|
|
||||||
|
File trackFile = new File(tracksDir, name + ".json");
|
||||||
|
if (!trackFile.exists()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean success = doRead(trackFile, reader -> {
|
||||||
|
reader.beginObject();
|
||||||
|
reader.nextName(); // name record
|
||||||
|
reader.nextString(); // name
|
||||||
|
reader.nextName(); // groups record
|
||||||
|
reader.beginArray();
|
||||||
|
while (reader.hasNext()) {
|
||||||
|
groups.add(reader.nextString());
|
||||||
|
}
|
||||||
|
reader.endArray();
|
||||||
|
reader.endObject();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
track.setGroups(groups);
|
||||||
|
if (success) plugin.getTrackManager().updateOrSet(track);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean loadAllTracks() {
|
||||||
|
String[] fileNames = tracksDir.list((dir, name) -> name.endsWith(".json"));
|
||||||
|
if (fileNames == null) return false;
|
||||||
|
List<String> tracks = Arrays.stream(fileNames)
|
||||||
|
.map(s -> s.substring(0, s.length() - 5))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
plugin.getTrackManager().unloadAll();
|
||||||
|
tracks.forEach(this::loadTrack);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean saveTrack(Track track) {
|
||||||
|
File trackFile = new File(tracksDir, track.getName() + ".json");
|
||||||
|
if (!trackFile.exists()) {
|
||||||
|
try {
|
||||||
|
trackFile.createNewFile();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean success = doWrite(trackFile, writer -> {
|
||||||
|
writer.beginObject();
|
||||||
|
writer.name("name").value(track.getName());
|
||||||
|
writer.name("groups");
|
||||||
|
writer.beginArray();
|
||||||
|
for (String s : track.getGroups()) {
|
||||||
|
writer.value(s);
|
||||||
|
}
|
||||||
|
writer.endArray();
|
||||||
|
writer.endObject();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean deleteTrack(Track track) {
|
||||||
|
File trackFile = new File(tracksDir, track.getName() + ".json");
|
||||||
|
if (trackFile.exists()) {
|
||||||
|
trackFile.delete();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface WriteOperation {
|
||||||
|
boolean onRun(JsonWriter writer) throws IOException;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ReadOperation {
|
||||||
|
boolean onRun(JsonReader reader) throws IOException;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,378 @@
|
|||||||
|
/*
|
||||||
|
* 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 me.lucko.luckperms.groups.Group;
|
||||||
|
import me.lucko.luckperms.tracks.Track;
|
||||||
|
import me.lucko.luckperms.users.User;
|
||||||
|
import me.lucko.luckperms.utils.Node;
|
||||||
|
import org.yaml.snakeyaml.DumperOptions;
|
||||||
|
import org.yaml.snakeyaml.Yaml;
|
||||||
|
import org.yaml.snakeyaml.constructor.BaseConstructor;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static me.lucko.luckperms.core.PermissionHolder.exportToLegacy;
|
||||||
|
|
||||||
|
@SuppressWarnings({"unchecked", "ResultOfMethodCallIgnored"})
|
||||||
|
public class YAMLDatastore extends FlatfileDatastore {
|
||||||
|
public YAMLDatastore(LuckPermsPlugin plugin, File pluginDir) {
|
||||||
|
super(plugin, "Flatfile - YAML", pluginDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Yaml getYaml() {
|
||||||
|
DumperOptions options = new DumperOptions();
|
||||||
|
options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
|
||||||
|
return new Yaml(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean doRead(File file, ReadOperation readOperation) {
|
||||||
|
boolean success = false;
|
||||||
|
try {
|
||||||
|
@Cleanup FileReader fileReader = new FileReader(file);
|
||||||
|
@Cleanup BufferedReader bufferedReader = new BufferedReader(fileReader);
|
||||||
|
success = readOperation.onRun((Map<String, Object>) getYaml().load(bufferedReader));
|
||||||
|
} catch (Throwable t) {
|
||||||
|
t.printStackTrace();
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean doWrite(File file, Map<String, Object> values) {
|
||||||
|
try {
|
||||||
|
@Cleanup FileWriter fileWriter = new FileWriter(file);
|
||||||
|
@Cleanup BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
|
||||||
|
getYaml().dump(values, bufferedWriter);
|
||||||
|
bufferedWriter.flush();
|
||||||
|
return true;
|
||||||
|
} catch (Throwable t) {
|
||||||
|
t.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void childInit() throws Exception {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean loadUser(UUID uuid, String username) {
|
||||||
|
User user = plugin.getUserManager().make(uuid, username);
|
||||||
|
boolean success = false;
|
||||||
|
|
||||||
|
File userFile = new File(usersDir, uuid.toString() + ".yml");
|
||||||
|
if (userFile.exists()) {
|
||||||
|
final String[] name = {null};
|
||||||
|
success = doRead(userFile, values -> {
|
||||||
|
name[0] = (String) values.get("name");
|
||||||
|
user.setPrimaryGroup((String) values.get("primary-group"));
|
||||||
|
Map<String, Boolean> perms = (Map<String, Boolean>) values.get("perms");
|
||||||
|
for (Map.Entry<String, Boolean> e : perms.entrySet()) {
|
||||||
|
user.getNodes().add(Node.fromSerialisedNode(e.getKey(), e.getValue()));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (user.getName().equalsIgnoreCase("null")) {
|
||||||
|
user.setName(name[0]);
|
||||||
|
} else {
|
||||||
|
if (!name[0].equals(user.getName())) {
|
||||||
|
Map<String, Object> values = new HashMap<>();
|
||||||
|
values.put("uuid", user.getUuid().toString());
|
||||||
|
values.put("name", user.getName());
|
||||||
|
values.put("primary-group", user.getPrimaryGroup());
|
||||||
|
values.put("perms", exportToLegacy(user.getNodes()));
|
||||||
|
doWrite(userFile, values);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success) plugin.getUserManager().updateOrSet(user);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean saveUser(User user) {
|
||||||
|
File userFile = new File(usersDir, user.getUuid().toString() + ".yml");
|
||||||
|
if (!plugin.getUserManager().shouldSave(user)) {
|
||||||
|
if (userFile.exists()) {
|
||||||
|
userFile.delete();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!userFile.exists()) {
|
||||||
|
try {
|
||||||
|
userFile.createNewFile();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> values = new HashMap<>();
|
||||||
|
values.put("uuid", user.getUuid().toString());
|
||||||
|
values.put("name", user.getName());
|
||||||
|
values.put("primary-group", user.getPrimaryGroup());
|
||||||
|
values.put("perms", exportToLegacy(user.getNodes()));
|
||||||
|
return doWrite(userFile, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean cleanupUsers() {
|
||||||
|
File[] files = usersDir.listFiles((dir, name) -> name.endsWith(".yml"));
|
||||||
|
if (files == null) return false;
|
||||||
|
|
||||||
|
for (File file : files) {
|
||||||
|
Map<String, Boolean> nodes = new HashMap<>();
|
||||||
|
doRead(file, values -> {
|
||||||
|
Map<String, Boolean> perms = (Map<String, Boolean>) values.get("perms");
|
||||||
|
nodes.putAll(perms);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
boolean shouldDelete = false;
|
||||||
|
if (nodes.size() == 1) {
|
||||||
|
for (Map.Entry<String, Boolean> e : nodes.entrySet()) {
|
||||||
|
// There's only one
|
||||||
|
shouldDelete = e.getKey().equalsIgnoreCase("group.default") && e.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldDelete) {
|
||||||
|
file.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<UUID> getUniqueUsers() {
|
||||||
|
String[] fileNames = usersDir.list((dir, name) -> name.endsWith(".yml"));
|
||||||
|
if (fileNames == null) return null;
|
||||||
|
return Arrays.stream(fileNames)
|
||||||
|
.map(s -> s.substring(0, s.length() - 4))
|
||||||
|
.map(UUID::fromString)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean createAndLoadGroup(String name) {
|
||||||
|
Group group = plugin.getGroupManager().make(name);
|
||||||
|
|
||||||
|
File groupFile = new File(groupsDir, name + ".yml");
|
||||||
|
if (!groupFile.exists()) {
|
||||||
|
try {
|
||||||
|
groupFile.createNewFile();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> values = new HashMap<>();
|
||||||
|
values.put("name", group.getName());
|
||||||
|
values.put("perms", exportToLegacy(group.getNodes()));
|
||||||
|
|
||||||
|
if (!doWrite(groupFile, values)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean success = doRead(groupFile, values -> {
|
||||||
|
Map<String, Boolean> perms = (Map<String, Boolean>) values.get("perms");
|
||||||
|
for (Map.Entry<String, Boolean> e : perms.entrySet()) {
|
||||||
|
group.getNodes().add(Node.fromSerialisedNode(e.getKey(), e.getValue()));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (success) plugin.getGroupManager().updateOrSet(group);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean loadGroup(String name) {
|
||||||
|
Group group = plugin.getGroupManager().make(name);
|
||||||
|
|
||||||
|
File groupFile = new File(groupsDir, name + ".yml");
|
||||||
|
if (!groupFile.exists()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean success = doRead(groupFile, values -> {
|
||||||
|
Map<String, Boolean> perms = (Map<String, Boolean>) values.get("perms");
|
||||||
|
for (Map.Entry<String, Boolean> e : perms.entrySet()) {
|
||||||
|
group.getNodes().add(Node.fromSerialisedNode(e.getKey(), e.getValue()));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (success) plugin.getGroupManager().updateOrSet(group);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean loadAllGroups() {
|
||||||
|
String[] fileNames = groupsDir.list((dir, name) -> name.endsWith(".yml"));
|
||||||
|
if (fileNames == null) return false;
|
||||||
|
List<String> groups = Arrays.stream(fileNames)
|
||||||
|
.map(s -> s.substring(0, s.length() - 4))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
plugin.getGroupManager().unloadAll();
|
||||||
|
groups.forEach(this::loadGroup);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean saveGroup(Group group) {
|
||||||
|
File groupFile = new File(groupsDir, group.getName() + ".yml");
|
||||||
|
if (!groupFile.exists()) {
|
||||||
|
try {
|
||||||
|
groupFile.createNewFile();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> values = new HashMap<>();
|
||||||
|
values.put("name", group.getName());
|
||||||
|
values.put("perms", exportToLegacy(group.getNodes()));
|
||||||
|
return doWrite(groupFile, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean deleteGroup(Group group) {
|
||||||
|
File groupFile = new File(groupsDir, group.getName() + ".yml");
|
||||||
|
if (groupFile.exists()) {
|
||||||
|
groupFile.delete();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean createAndLoadTrack(String name) {
|
||||||
|
Track track = plugin.getTrackManager().make(name);
|
||||||
|
List<String> groups = new ArrayList<>();
|
||||||
|
|
||||||
|
File trackFile = new File(tracksDir, name + ".yml");
|
||||||
|
if (!trackFile.exists()) {
|
||||||
|
try {
|
||||||
|
trackFile.createNewFile();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> values = new HashMap<>();
|
||||||
|
values.put("name", track.getName());
|
||||||
|
values.put("groups", track.getGroups());
|
||||||
|
|
||||||
|
if (!doWrite(trackFile, values)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean success = doRead(trackFile, values -> {
|
||||||
|
groups.addAll((List<String>) values.get("groups"));
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
track.setGroups(groups);
|
||||||
|
if (success) plugin.getTrackManager().updateOrSet(track);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean loadTrack(String name) {
|
||||||
|
Track track = plugin.getTrackManager().make(name);
|
||||||
|
List<String> groups = new ArrayList<>();
|
||||||
|
|
||||||
|
File trackFile = new File(tracksDir, name + ".yml");
|
||||||
|
if (!trackFile.exists()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean success = doRead(trackFile, values -> {
|
||||||
|
groups.addAll((List<String>) values.get("groups"));
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
track.setGroups(groups);
|
||||||
|
if (success) plugin.getTrackManager().updateOrSet(track);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean loadAllTracks() {
|
||||||
|
String[] fileNames = tracksDir.list((dir, name) -> name.endsWith(".yml"));
|
||||||
|
if (fileNames == null) return false;
|
||||||
|
List<String> tracks = Arrays.stream(fileNames)
|
||||||
|
.map(s -> s.substring(0, s.length() - 4))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
plugin.getTrackManager().unloadAll();
|
||||||
|
tracks.forEach(this::loadTrack);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean saveTrack(Track track) {
|
||||||
|
File trackFile = new File(tracksDir, track.getName() + ".yml");
|
||||||
|
if (!trackFile.exists()) {
|
||||||
|
try {
|
||||||
|
trackFile.createNewFile();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> values = new HashMap<>();
|
||||||
|
values.put("name", track.getName());
|
||||||
|
values.put("groups", track.getGroups());
|
||||||
|
return doWrite(trackFile, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean deleteTrack(Track track) {
|
||||||
|
File trackFile = new File(tracksDir, track.getName() + ".yml");
|
||||||
|
if (trackFile.exists()) {
|
||||||
|
trackFile.delete();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ReadOperation {
|
||||||
|
boolean onRun(Map<String, Object> values) throws IOException;
|
||||||
|
}
|
||||||
|
}
|
@ -43,7 +43,7 @@ apply-shorthand=true
|
|||||||
log-notify=true
|
log-notify=true
|
||||||
|
|
||||||
# Which storage method the plugin should use.
|
# Which storage method the plugin should use.
|
||||||
# Currently supported: mysql, sqlite, h2, flatfile, mongodb
|
# Currently supported: mysql, sqlite, h2, json, yaml, mongodb
|
||||||
# Fill out connection info below if you're using MySQL or MongoDB
|
# Fill out connection info below if you're using MySQL or MongoDB
|
||||||
storage-method="h2"
|
storage-method="h2"
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user