Implement persisting subjects (+ defaults)
This commit is contained in:
parent
069e535f1a
commit
5b4975f34c
@ -29,6 +29,8 @@ import me.lucko.luckperms.LPSpongePlugin;
|
||||
import me.lucko.luckperms.api.sponge.collections.GroupCollection;
|
||||
import me.lucko.luckperms.api.sponge.collections.UserCollection;
|
||||
import me.lucko.luckperms.api.sponge.simple.SimpleCollection;
|
||||
import me.lucko.luckperms.api.sponge.simple.persisted.SimplePersistedCollection;
|
||||
import me.lucko.luckperms.api.sponge.simple.persisted.SubjectStorage;
|
||||
import me.lucko.luckperms.contexts.SpongeCalculatorLink;
|
||||
import org.spongepowered.api.plugin.PluginContainer;
|
||||
import org.spongepowered.api.service.context.ContextCalculator;
|
||||
@ -36,21 +38,31 @@ import org.spongepowered.api.service.permission.*;
|
||||
import org.spongepowered.api.text.Text;
|
||||
import org.spongepowered.api.util.Tristate;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* The LuckPerms implementation of the Sponge Permission Service
|
||||
*/
|
||||
public class LuckPermsService implements PermissionService {
|
||||
public static final String SERVER_CONTEXT = "server";
|
||||
|
||||
@Getter
|
||||
private final LPSpongePlugin plugin;
|
||||
|
||||
@Getter
|
||||
private final SubjectStorage storage;
|
||||
|
||||
@Getter
|
||||
private final UserCollection userSubjects;
|
||||
|
||||
@Getter
|
||||
private final GroupCollection groupSubjects;
|
||||
|
||||
@Getter
|
||||
private final SimplePersistedCollection defaultSubjects;
|
||||
|
||||
@Getter
|
||||
private final Set<PermissionDescription> descriptionSet;
|
||||
|
||||
@ -59,12 +71,17 @@ public class LuckPermsService implements PermissionService {
|
||||
public LuckPermsService(LPSpongePlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
|
||||
storage = new SubjectStorage(new File(plugin.getDataFolder(), "local"));
|
||||
|
||||
userSubjects = new UserCollection(this, plugin.getUserManager());
|
||||
groupSubjects = new GroupCollection(this, plugin.getGroupManager());
|
||||
defaultSubjects = new SimplePersistedCollection(this, "defaults");
|
||||
defaultSubjects.loadAll();
|
||||
|
||||
subjects = new ConcurrentHashMap<>();
|
||||
subjects.put(PermissionService.SUBJECTS_USER, userSubjects);
|
||||
subjects.put(PermissionService.SUBJECTS_GROUP, groupSubjects);
|
||||
subjects.put("defaults", defaultSubjects);
|
||||
|
||||
descriptionSet = ConcurrentHashMap.newKeySet();
|
||||
}
|
||||
@ -75,7 +92,7 @@ public class LuckPermsService implements PermissionService {
|
||||
|
||||
@Override
|
||||
public Subject getDefaults() {
|
||||
return getSubjects("defaults").get("default");
|
||||
return getDefaultSubjects().get("default");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -89,6 +89,6 @@ public class GroupCollection implements SubjectCollection {
|
||||
|
||||
@Override
|
||||
public Subject getDefaults() {
|
||||
return service.getDefaults();
|
||||
return service.getDefaultSubjects().get(getIdentifier());
|
||||
}
|
||||
}
|
||||
|
@ -161,6 +161,6 @@ public class UserCollection implements SubjectCollection {
|
||||
|
||||
@Override
|
||||
public Subject getDefaults() {
|
||||
return service.getDefaults();
|
||||
return service.getDefaultSubjects().get(getIdentifier());
|
||||
}
|
||||
}
|
||||
|
@ -25,8 +25,8 @@ package me.lucko.luckperms.api.sponge.simple;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import me.lucko.luckperms.api.sponge.LuckPermsService;
|
||||
import org.spongepowered.api.service.context.Context;
|
||||
import org.spongepowered.api.service.permission.PermissionService;
|
||||
import org.spongepowered.api.service.permission.Subject;
|
||||
import org.spongepowered.api.service.permission.SubjectCollection;
|
||||
import org.spongepowered.api.util.Tristate;
|
||||
@ -37,9 +37,12 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Super simple SubjectCollection implementation
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class SimpleCollection implements SubjectCollection {
|
||||
private final PermissionService service;
|
||||
private final LuckPermsService service;
|
||||
|
||||
@Getter
|
||||
private final String identifier;
|
||||
@ -85,6 +88,6 @@ public class SimpleCollection implements SubjectCollection {
|
||||
|
||||
@Override
|
||||
public Subject getDefaults() {
|
||||
return new SimpleSubject("default", service, this);
|
||||
return service.getDefaultSubjects().get(identifier);
|
||||
}
|
||||
}
|
||||
|
@ -66,11 +66,6 @@ public class SimpleSubject implements Subject {
|
||||
return getPermissionValue(contexts, node).asBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(@NonNull String permission) {
|
||||
return hasPermission(getActiveContexts(), permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tristate getPermissionValue(@NonNull Set<Context> contexts, @NonNull String node) {
|
||||
Tristate res = subjectData.getNodeTree(contexts).get(node);
|
||||
@ -86,21 +81,11 @@ public class SimpleSubject implements Subject {
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChildOf(@NonNull Subject parent) {
|
||||
return isChildOf(getActiveContexts(), parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChildOf(@NonNull Set<Context> contexts, @NonNull Subject subject) {
|
||||
return subjectData.getParents(contexts).contains(subject);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Subject> getParents() {
|
||||
return getParents(getActiveContexts());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Subject> getParents(@NonNull Set<Context> contexts) {
|
||||
return subjectData.getParents(contexts);
|
||||
@ -121,11 +106,6 @@ public class SimpleSubject implements Subject {
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<String> getOption(String key) {
|
||||
return getOption(getActiveContexts(), key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Context> getActiveContexts() {
|
||||
return SubjectData.GLOBAL_CONTEXT;
|
||||
|
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.sponge.simple.persisted;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import me.lucko.luckperms.api.sponge.LuckPermsService;
|
||||
import org.spongepowered.api.service.context.Context;
|
||||
import org.spongepowered.api.service.permission.Subject;
|
||||
import org.spongepowered.api.service.permission.SubjectCollection;
|
||||
import org.spongepowered.api.util.Tristate;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* A simple persistable subject collection
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class SimplePersistedCollection implements SubjectCollection {
|
||||
private final LuckPermsService service;
|
||||
|
||||
@Getter
|
||||
private final String identifier;
|
||||
|
||||
private final Map<String, SimplePersistedSubject> subjects = new ConcurrentHashMap<>();
|
||||
|
||||
public void loadAll() {
|
||||
Map<String, SimpleSubjectDataHolder> holders = service.getStorage().loadAllFromFile(identifier);
|
||||
for (Map.Entry<String, SimpleSubjectDataHolder> e : holders.entrySet()) {
|
||||
SimplePersistedSubject subject = new SimplePersistedSubject(e.getKey(), service, this);
|
||||
subject.loadData(e.getValue());
|
||||
subjects.put(e.getKey(), subject);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized Subject get(@NonNull String id) {
|
||||
if (!subjects.containsKey(id)) {
|
||||
subjects.put(id, new SimplePersistedSubject(id, service, this));
|
||||
}
|
||||
|
||||
return subjects.get(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasRegistered(@NonNull String id) {
|
||||
return subjects.containsKey(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<Subject> getAllSubjects() {
|
||||
return subjects.values().stream().map(s -> (Subject) s).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Subject, Boolean> getAllWithPermission(@NonNull String id) {
|
||||
return getAllWithPermission(Collections.emptySet(), id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Subject, Boolean> getAllWithPermission(@NonNull Set<Context> contexts, @NonNull String node) {
|
||||
Map<Subject, Boolean> m = new HashMap<>();
|
||||
for (Subject subject : subjects.values()) {
|
||||
Tristate ts = subject.getPermissionValue(contexts, node);
|
||||
if (ts != Tristate.UNDEFINED) {
|
||||
m.put(subject, ts.asBoolean());
|
||||
}
|
||||
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Subject getDefaults() {
|
||||
return service.getDefaultSubjects().get(identifier);
|
||||
}
|
||||
}
|
@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.sponge.simple.persisted;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import me.lucko.luckperms.api.sponge.LuckPermsService;
|
||||
import org.spongepowered.api.command.CommandSource;
|
||||
import org.spongepowered.api.service.context.Context;
|
||||
import org.spongepowered.api.service.permission.MemorySubjectData;
|
||||
import org.spongepowered.api.service.permission.Subject;
|
||||
import org.spongepowered.api.service.permission.SubjectCollection;
|
||||
import org.spongepowered.api.service.permission.SubjectData;
|
||||
import org.spongepowered.api.util.Tristate;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A simple persistable Subject implementation
|
||||
*/
|
||||
@Getter
|
||||
public class SimplePersistedSubject implements Subject {
|
||||
private final String identifier;
|
||||
|
||||
private final LuckPermsService service;
|
||||
private final SubjectCollection containingCollection;
|
||||
private final SimplePersistedSubjectData subjectData;
|
||||
private final MemorySubjectData transientSubjectData;
|
||||
|
||||
public SimplePersistedSubject(String identifier, LuckPermsService service, SubjectCollection containingCollection) {
|
||||
this.identifier = identifier;
|
||||
this.service = service;
|
||||
this.containingCollection = containingCollection;
|
||||
this.subjectData = new SimplePersistedSubjectData(service, this);
|
||||
this.transientSubjectData = new MemorySubjectData(service);
|
||||
}
|
||||
|
||||
public void loadData(SimpleSubjectDataHolder dataHolder) {
|
||||
subjectData.setSave(false);
|
||||
dataHolder.copyTo(subjectData, service);
|
||||
subjectData.setSave(true);
|
||||
}
|
||||
|
||||
public void save() {
|
||||
service.getPlugin().doAsync(() -> {
|
||||
try {
|
||||
service.getStorage().saveToFile(this);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<CommandSource> getCommandSource() {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(@NonNull Set<Context> contexts, @NonNull String node) {
|
||||
return getPermissionValue(contexts, node).asBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tristate getPermissionValue(@NonNull Set<Context> contexts, @NonNull String node) {
|
||||
Tristate res = subjectData.getNodeTree(contexts).get(node);
|
||||
if (res == Tristate.UNDEFINED) {
|
||||
transientSubjectData.getNodeTree(contexts).get(node);
|
||||
}
|
||||
if (res == Tristate.UNDEFINED) {
|
||||
for (Subject parent : getParents(contexts)) {
|
||||
Tristate tempRes = parent.getPermissionValue(contexts, node);
|
||||
if (tempRes != Tristate.UNDEFINED) {
|
||||
res = tempRes;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChildOf(@NonNull Set<Context> contexts, @NonNull Subject subject) {
|
||||
return subjectData.getParents(contexts).contains(subject) || transientSubjectData.getParents(contexts).contains(subject);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Subject> getParents(@NonNull Set<Context> contexts) {
|
||||
List<Subject> s = new ArrayList<>();
|
||||
s.addAll(subjectData.getParents(contexts));
|
||||
s.addAll(transientSubjectData.getParents(contexts));
|
||||
return s;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<String> getOption(Set<Context> set, String key) {
|
||||
Optional<String> res = Optional.ofNullable(subjectData.getOptions(getActiveContexts()).get(key));
|
||||
if (!res.isPresent()) {
|
||||
res = Optional.ofNullable(transientSubjectData.getOptions(getActiveContexts()).get(key));
|
||||
}
|
||||
if (!res.isPresent()) {
|
||||
for (Subject parent : getParents(getActiveContexts())) {
|
||||
Optional<String> tempRes = parent.getOption(getActiveContexts(), key);
|
||||
if (tempRes.isPresent()) {
|
||||
res = tempRes;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Context> getActiveContexts() {
|
||||
return SubjectData.GLOBAL_CONTEXT;
|
||||
}
|
||||
}
|
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.sponge.simple.persisted;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.spongepowered.api.service.context.Context;
|
||||
import org.spongepowered.api.service.permission.MemorySubjectData;
|
||||
import org.spongepowered.api.service.permission.PermissionService;
|
||||
import org.spongepowered.api.service.permission.Subject;
|
||||
import org.spongepowered.api.util.Tristate;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Extension of MemorySubjectData which persists data when modified
|
||||
*/
|
||||
public class SimplePersistedSubjectData extends MemorySubjectData {
|
||||
private final SimplePersistedSubject subject;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private boolean save = true;
|
||||
|
||||
public SimplePersistedSubjectData(PermissionService service, SimplePersistedSubject subject) {
|
||||
super(service);
|
||||
this.subject = subject;
|
||||
}
|
||||
|
||||
private void save() {
|
||||
if (!save) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (subject != null) {
|
||||
subject.save();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setPermission(Set<Context> contexts, String permission, Tristate value) {
|
||||
boolean r = super.setPermission(contexts, permission, value);
|
||||
save();
|
||||
return r;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clearPermissions() {
|
||||
boolean r = super.clearPermissions();
|
||||
save();
|
||||
return r;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clearPermissions(Set<Context> context) {
|
||||
boolean r = super.clearPermissions(context);
|
||||
save();
|
||||
return r;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addParent(Set<Context> contexts, Subject parent) {
|
||||
boolean r = super.addParent(contexts, parent);
|
||||
save();
|
||||
return r;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeParent(Set<Context> contexts, Subject parent) {
|
||||
boolean r = super.removeParent(contexts, parent);
|
||||
save();
|
||||
return r;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clearParents() {
|
||||
boolean r = super.clearParents();
|
||||
save();
|
||||
return r;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clearParents(Set<Context> contexts) {
|
||||
boolean r = super.clearParents(contexts);
|
||||
save();
|
||||
return r;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setOption(Set<Context> contexts, String key, @Nullable String value) {
|
||||
boolean r = super.setOption(contexts, key, value);
|
||||
save();
|
||||
return r;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clearOptions(Set<Context> contexts) {
|
||||
boolean r = super.clearOptions(contexts);
|
||||
save();
|
||||
return r;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clearOptions() {
|
||||
boolean r = super.clearOptions();
|
||||
save();
|
||||
return r;
|
||||
}
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.sponge.simple.persisted;
|
||||
|
||||
import org.spongepowered.api.service.context.Context;
|
||||
import org.spongepowered.api.service.permission.MemorySubjectData;
|
||||
import org.spongepowered.api.service.permission.PermissionService;
|
||||
import org.spongepowered.api.util.Tristate;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Holds SubjectData in a "gson friendly" format for serialization
|
||||
*/
|
||||
public class SimpleSubjectDataHolder {
|
||||
private final Map<Map<String, String>, Map<String, Boolean>> permissions;
|
||||
private final Map<Map<String, String>, Map<String, String>> options;
|
||||
private final Map<Map<String, String>, List<Map.Entry<String, String>>> parents;
|
||||
|
||||
public SimpleSubjectDataHolder(Map<Set<Context>, Map<String, String>> options, Map<Set<Context>, Map<String, Boolean>> permissions, Map<Set<Context>, List<Map.Entry<String, String>>> parents) {
|
||||
this.options = new HashMap<>();
|
||||
for (Map.Entry<Set<Context>, Map<String, String>> e : options.entrySet()) {
|
||||
this.options.put(convertContexts(e.getKey()), new HashMap<>(e.getValue()));
|
||||
}
|
||||
|
||||
this.permissions = new HashMap<>();
|
||||
for (Map.Entry<Set<Context>, Map<String, Boolean>> e : permissions.entrySet()) {
|
||||
this.permissions.put(convertContexts(e.getKey()), new HashMap<>(e.getValue()));
|
||||
}
|
||||
|
||||
this.parents = new HashMap<>();
|
||||
for (Map.Entry<Set<Context>, List<Map.Entry<String, String>>> e : parents.entrySet()) {
|
||||
this.parents.put(convertContexts(e.getKey()), e.getValue().stream().map(p -> new AbstractMap.SimpleEntry<>(p.getKey(), p.getValue())).collect(Collectors.toList()));
|
||||
}
|
||||
}
|
||||
|
||||
public SimpleSubjectDataHolder(MemorySubjectData data) {
|
||||
this(
|
||||
data.getAllOptions(),
|
||||
data.getAllPermissions(),
|
||||
data.getAllParents().entrySet().stream()
|
||||
.collect(Collectors.toMap(
|
||||
Map.Entry::getKey,
|
||||
e -> e.getValue().stream()
|
||||
.map(s -> new AbstractMap.SimpleEntry<>(
|
||||
s.getContainingCollection().getIdentifier(),
|
||||
s.getIdentifier())
|
||||
)
|
||||
.collect(Collectors.toList())
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public void copyTo(MemorySubjectData subjectData, PermissionService service) {
|
||||
for (Map.Entry<Map<String, String>, Map<String, Boolean>> e : permissions.entrySet()) {
|
||||
for (Map.Entry<String, Boolean> perm : e.getValue().entrySet()) {
|
||||
subjectData.setPermission(convertContexts(e.getKey()), perm.getKey(), Tristate.fromBoolean(perm.getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
for (Map.Entry<Map<String, String>, Map<String, String>> e : options.entrySet()) {
|
||||
for (Map.Entry<String, String> option : e.getValue().entrySet()) {
|
||||
subjectData.setOption(convertContexts(e.getKey()), option.getKey(), option.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
for (Map.Entry<Map<String, String>, List<Map.Entry<String, String>>> e : parents.entrySet()) {
|
||||
for (Map.Entry<String, String> parent : e.getValue()) {
|
||||
subjectData.addParent(convertContexts(e.getKey()), service.getSubjects(parent.getKey()).get(parent.getValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Map<String, String> convertContexts(Set<Context> contexts) {
|
||||
return contexts.stream().collect(Collectors.toMap(Context::getKey, Context::getValue));
|
||||
}
|
||||
|
||||
public static Set<Context> convertContexts(Map<String, String> contexts) {
|
||||
return contexts.entrySet().stream().map(e -> new Context(e.getKey(), e.getValue())).collect(Collectors.toSet());
|
||||
}
|
||||
}
|
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.api.sponge.simple.persisted;
|
||||
|
||||
import com.google.common.io.Files;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.AbstractMap;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Handles persisted Subject I/O and (de)serialization
|
||||
*/
|
||||
public class SubjectStorage {
|
||||
private final Gson gson;
|
||||
private final File container;
|
||||
|
||||
public SubjectStorage(File container) {
|
||||
this.gson = new GsonBuilder().setPrettyPrinting().enableComplexMapKeySerialization().create();
|
||||
this.container = container;
|
||||
checkContainer();
|
||||
}
|
||||
|
||||
private void checkContainer() {
|
||||
this.container.getParentFile().mkdirs();
|
||||
}
|
||||
|
||||
public void saveToFile(SimplePersistedSubject subject) throws IOException {
|
||||
checkContainer();
|
||||
File collection = new File(container, subject.getContainingCollection().getIdentifier());
|
||||
if (!collection.exists()) {
|
||||
collection.mkdirs();
|
||||
}
|
||||
|
||||
File subjectFile = new File(collection, subject.getIdentifier().toLowerCase() + ".json");
|
||||
saveToFile(subject, subjectFile);
|
||||
}
|
||||
|
||||
public void saveToFile(SimplePersistedSubject subject, File file) throws IOException {
|
||||
file.getParentFile().mkdirs();
|
||||
if (file.exists()) {
|
||||
file.delete();
|
||||
}
|
||||
file.createNewFile();
|
||||
|
||||
Files.write(saveToString(new SimpleSubjectDataHolder(subject.getSubjectData())), file, Charset.defaultCharset());
|
||||
}
|
||||
|
||||
public String saveToString(SimpleSubjectDataHolder subject) {
|
||||
return gson.toJson(subject);
|
||||
}
|
||||
|
||||
public Map<String, SimpleSubjectDataHolder> loadAllFromFile(String collectionName) {
|
||||
checkContainer();
|
||||
File collection = new File(container, collectionName);
|
||||
if (!collection.exists()) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
String[] fileNames = collection.list((dir, name) -> name.endsWith(".json"));
|
||||
if (fileNames == null) return Collections.emptyMap();
|
||||
|
||||
Map<String, SimpleSubjectDataHolder> holders = new HashMap<>();
|
||||
for (String name : fileNames) {
|
||||
File subject = new File(collection, name);
|
||||
|
||||
try {
|
||||
Map.Entry<String, SimpleSubjectDataHolder> s = loadFromFile(subject);
|
||||
if (s != null) {
|
||||
holders.put(s.getKey(), s.getValue());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
return holders;
|
||||
}
|
||||
|
||||
public Map.Entry<String, SimpleSubjectDataHolder> loadFromFile(String collectionName, String subjectName) throws IOException {
|
||||
checkContainer();
|
||||
File collection = new File(container, collectionName);
|
||||
if (!collection.exists()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
File subject = new File(collection, subjectName.toLowerCase() + ".json");
|
||||
return new AbstractMap.SimpleEntry<>(subjectName.toLowerCase(), loadFromFile(subject).getValue());
|
||||
}
|
||||
|
||||
public Map.Entry<String, SimpleSubjectDataHolder> loadFromFile(File file) throws IOException {
|
||||
if (!file.exists()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String s = Files.toString(file, Charset.defaultCharset());
|
||||
return new AbstractMap.SimpleEntry<>(file.getName().substring(file.getName().length() - 5).toLowerCase(), loadFromString(s));
|
||||
}
|
||||
|
||||
public SimpleSubjectDataHolder loadFromString(String s) {
|
||||
return gson.fromJson(s, SimpleSubjectDataHolder.class);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user