Compare commits

...
17 Commits
Author SHA1 Message Date
Luck 4aa753515d Add events 2016-08-20 15:43:54 +01:00
Luck 7e933966cf revert remove sources 2016-08-20 02:19:03 +01:00
Luck b4d179f7b2 use a proper repo instead of the rubbish jenkins one 2016-08-20 01:39:19 +01:00
Luck a51acdbc88 remove sources 2016-08-19 22:23:28 +01:00
Luck 52e63a228d Update readme 2016-08-19 21:54:40 +01:00
Luck 9424d2d2ba Process shorthand in server/world names 2016-08-19 19:36:04 +01:00
Luck 0c12eebe6f Check temporary permissions separately to the sync task 2016-08-19 19:10:36 +01:00
Luck a15a0752f4 Add support for MongoDB and H2 database formats 2016-08-19 18:21:16 +01:00
Luck 31cef46b56 Fix sponge tab complete, fix bungee listeners & change some messages 2016-08-18 20:14:12 +01:00
Luck bfe0126816 fix format 2016-08-18 13:52:38 +01:00
Luck 98b56691dd Allow expiry timestamp for temporary assignment args 2016-08-18 13:51:31 +01:00
Luck 6451175d0e Fix some broken messages 2016-08-18 12:47:33 +01:00
Luck 9b4319c42d fix readme 2016-08-18 12:33:46 +01:00
Luck e9e7d81ddf Add import/export support 2016-08-18 12:30:51 +01:00
Luck 84afbf26f8 refactor LogEntry & cleanup stream formatting 2016-08-18 00:07:56 +01:00
Luck ca9037461a remove lombok from api and attach sources 2016-08-15 16:09:16 +02:00
Luck 9a3eeca411 idk 2016-08-15 12:06:36 +02:00
114 changed files with 3123 additions and 740 deletions

No files matched your search

+47 -5
View File
@@ -5,6 +5,11 @@ A permissions implementation for Bukkit/Spigot, BungeeCord and Sponge.
* **Development Builds** - <https://ci.lucko.me/job/LuckPerms>
* **Javadocs** - <https://jd.lucko.me/LuckPerms>
## Why LuckPerms?
_Features checked on 19th Aug 2016. If you find any inaccuracies, please do let me know. I tried to be as fair as possible, and copy all major features from the respective plugin pages._
![alt text](https://static.lucko.me/luckperms-compare.png "Feature comparison")
## Features
* **Group inheritance** - users can be members of multiple groups, groups can inherit other groups
* **Temporary permissions** - users/groups can be given permissions that expire after a given time
@@ -18,6 +23,7 @@ A permissions implementation for Bukkit/Spigot, BungeeCord and Sponge.
* **Vault Support** - hooks into Vault to integrate with other plugins
* **Developer API** - easily integrate LuckPerms into your own projects
* **Advanced action logging** - keep track of permission changes over time
* **Easily switch between storage systems** - export a log file from one datastore and import it into another
* **Easy and simple setup and configuration using commands** - no editing yml files, yuck
* **Negated permissions and groups** - define special rules for certain users/groups
* **Regex permissions** - define special permissions using regex
@@ -29,7 +35,7 @@ A permissions implementation for Bukkit/Spigot, BungeeCord and Sponge.
* **Open Sourced, Free...** - you shouldn't have to pay $10+ for a "powerful" permissions plugin.
* **BungeeCord compatible** - permissions, users and groups are synced across all LuckPerms instances
* **Sponge compatible** - permissions, users and groups are synced across all LuckPerms instances (bukkit --> sponge, for example)
* **Support for MySQL, SQLite & Flatfile (JSON)** - other storage methods coming soon (maybe)
* **Support for MySQL, MongoDB, SQLite, H2 & Flatfile (JSON)** - other storage methods coming soon (maybe)
## Setup
All configuration options are in the **config.yml/luckperms.conf** file, which is generated automagically when the plugin first starts.
@@ -65,9 +71,7 @@ Example: if a user has a global "fly.use" permission, and then has a negated "fl
Example: A user is a member of the default group, which grants "some.thing.perm", but the users own permissions has "some.thing.perm" set to false. The inherited permission will be overridden by the users own permissions, and the user will be granted the negative node.
### Temporary Permissions
Temporary permissions are checked each time a user/group is loaded, and when the sync task runs. This means if you set a temporary permission to expire after 30 seconds, it won't actually be removed until the sync task runs.
The only way around this is to decrease the sync interval.
Temporary permissions are audited once every 3 seconds, to check if they have expired. This check happens regardless of the sync interval setting. This means that you can safely set temporary permissions to expire after a matter of seconds, and they will be removed on-time.
### Shorthand Permissions
LuckPerms has it's own system (although it's quite similar to PermissionsEx :P) that allows you to set permissions in a shorthand format.
@@ -148,11 +152,46 @@ You can add LuckPerms as a Maven dependency by adding the following to your proj
<dependency>
<groupId>me.lucko.luckperms</groupId>
<artifactId>luckperms-api</artifactId>
<version>2.1</version>
<version>2.5</version>
</dependency>
</dependencies>
````
### Events
LuckPerms exposes a full read/write API, as well as an event listening system. Due to the multi-platform nature of the project, an internal Event system is used, as opposed to the systems already in place on each platform. (the Bukkit Event api, for example). This means that simply registering your listener with the platform is not sufficient.
All events are *fired asynchronously*. This means you should not interact with or call any non-thread safe methods from within listeners.
To listen to an event, you need to first make a class that implements `LPListener`. Then within this class, you can define all of your listener methods.
Each listener method must be annotated with `@Subscribe`. For example...
```java
package me.lucko.test;
import com.google.common.eventbus.Subscribe;
import me.lucko.luckperms.api.event.LPListener;
import me.lucko.luckperms.api.event.events.PermissionSetEvent;
public class TestListener implements LPListener {
@Subscribe
public void onPermissionSet(PermissionSetEvent event) {
}
}
```
You also need to register your new Listener with the API.
```java
@Override
public void onEnable() {
LuckPermsApi api;
api.registerListener(new TestListener());
}
```
## Versioning
As of version 2.0, LuckPerms roughly follows the standards set out in Semantic Versioning.
@@ -181,12 +220,14 @@ Additionally, you can use wildcards to grant users access to a selection of comm
* **All user commands** - luckperms.user.*
* **All group commands** - luckperms.group.*
* **All track commands** - luckperms.track.*
* **All log commands** - luckperms.log.*
### General
* /perms - n/a
* /perms sync - luckperms.sync
* /perms info - luckperms.info
* /perms debug - luckperms.debug
* /perms import \<file\> - luckperms.import
* /perms creategroup \<group\> - luckperms.creategroup
* /perms deletegroup \<group\> - luckperms.deletegroup
* /perms listgroups - luckperms.listgroups
@@ -242,6 +283,7 @@ Additionally, you can use wildcards to grant users access to a selection of comm
* /perms log recent [user] [page] - luckperms.log.recent
* /perms log search \<query\> [page] - luckperms.log.search
* /perms log notify [on|off] - luckperms.log.notify
* /perms log export \<file\> - luckperms.log.export
* /perms log userhistory \<user\> [page] - luckperms.log.userhistory
* /perms log grouphistory \<group\> [page] - luckperms.log.grouphistory
* /perms log trackhistory \<track\> [page] - luckperms.log.trackhistory
+12 -1
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId>
<version>2.3</version>
<version>2.5-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -23,4 +23,15 @@
</plugin>
</plugins>
</build>
<dependencies>
<!-- guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>19.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
@@ -22,8 +22,6 @@
package me.lucko.luckperms;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import me.lucko.luckperms.api.LuckPermsApi;
import java.util.Optional;
@@ -31,12 +29,9 @@ import java.util.Optional;
/**
* Static access to LuckPerms
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class LuckPerms {
private static LuckPermsApi api = null;
/**
* Gets an instance of {@link LuckPermsApi}
* @return an api instance
@@ -66,4 +61,8 @@ public final class LuckPerms {
api = null;
}
private LuckPerms() {
throw new UnsupportedOperationException("This class cannot be instantiated.");
}
}
@@ -22,6 +22,7 @@
package me.lucko.luckperms.api;
import me.lucko.luckperms.api.data.DatastoreConfiguration;
import me.lucko.luckperms.api.data.MySQLConfiguration;
/**
@@ -76,9 +77,17 @@ public interface LPConfiguration {
/**
* @return the database values set in the configuration
* @deprecated use {@link #getDatastoreConfig()}
*/
@SuppressWarnings("deprecation")
@Deprecated
MySQLConfiguration getDatabaseValues();
/**
* @return the values set for data storage in the configuration
*/
DatastoreConfiguration getDatastoreConfig();
/**
* @return the storage method string from the configuration
*/
@@ -22,29 +22,59 @@
package me.lucko.luckperms.api;
import lombok.*;
import java.util.UUID;
@Getter
@Builder
@ToString
@EqualsAndHashCode
@AllArgsConstructor
public final class LogEntry implements Comparable<LogEntry> {
public class LogEntry implements Comparable<LogEntry> {
public static LogEntryBuilder builder() {
return new LogEntryBuilder();
}
private static final String FORMAT = "&8(&e%s&8) [&a%s&8] (&b%s&8) &7--> &f%s";
@NonNull private final long timestamp;
@NonNull private final UUID actor;
@NonNull private final String actorName;
@NonNull private final char type;
private final UUID acted;
@NonNull private final String actedName;
@NonNull private final String action;
private long timestamp;
private UUID actor;
private String actorName;
private char type;
private UUID acted;
private String actedName;
private String action;
public LogEntry(long timestamp, UUID actor, String actorName, char type, UUID acted, String actedName, String action) {
if (actor == null) {
throw new NullPointerException("actor");
}
if (actorName == null) {
throw new NullPointerException("actorName");
}
if (actedName == null) {
throw new NullPointerException("actedName");
}
if (action == null) {
throw new NullPointerException("action");
}
this.timestamp = timestamp;
this.actor = actor;
this.actorName = actorName;
this.type = type;
this.acted = acted;
this.actedName = actedName;
this.action = action;
}
protected LogEntry() {
this.timestamp = 0L;
this.actor = null;
this.actorName = null;
this.type = Character.MIN_VALUE;
this.acted = null;
this.actedName = null;
this.action = null;
}
@Override
public int compareTo(LogEntry o) {
return Long.compare(timestamp, o.getTimestamp());
return equals(o) ? 0 : (Long.compare(timestamp, o.getTimestamp()) == 0 ? 1 : Long.compare(timestamp, o.getTimestamp()));
}
public boolean matchesSearch(String query) {
@@ -55,10 +85,231 @@ public final class LogEntry implements Comparable<LogEntry> {
public String getFormatted() {
return String.format(FORMAT,
getActorName(),
Character.toString(getType()),
getActedName(),
getAction()
actorName,
Character.toString(type),
actedName,
action
);
}
public long getTimestamp() {
return timestamp;
}
public UUID getActor() {
return actor;
}
public String getActorName() {
return actorName;
}
public char getType() {
return type;
}
public UUID getActed() {
return acted;
}
public String getActedName() {
return actedName;
}
public String getAction() {
return action;
}
void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
void setActor(UUID actor) {
this.actor = actor;
}
void setActorName(String actorName) {
this.actorName = actorName;
}
void setType(char type) {
this.type = type;
}
void setActed(UUID acted) {
this.acted = acted;
}
void setActedName(String actedName) {
this.actedName = actedName;
}
void setAction(String action) {
this.action = action;
}
@Override
public String toString() {
return "LogEntry(timestamp=" + this.getTimestamp() + ", actor=" + this.getActor() + ", actorName=" +
this.getActorName() + ", type=" + this.getType() + ", acted=" + this.getActed() + ", actedName=" +
this.getActedName() + ", action=" + this.getAction() + ")";
}
@Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof LogEntry)) return false;
final LogEntry other = (LogEntry) o;
if (this.getTimestamp() != other.getTimestamp()) return false;
final Object this$actor = this.getActor();
final Object other$actor = other.getActor();
if (this$actor == null ? other$actor != null : !this$actor.equals(other$actor)) return false;
final Object this$actorName = this.getActorName();
final Object other$actorName = other.getActorName();
if (this$actorName == null ? other$actorName != null : !this$actorName.equals(other$actorName)) return false;
if (this.getType() != other.getType()) return false;
final Object this$acted = this.getActed();
final Object other$acted = other.getActed();
if (this$acted == null ? other$acted != null : !this$acted.equals(other$acted)) return false;
final Object this$actedName = this.getActedName();
final Object other$actedName = other.getActedName();
if (this$actedName == null ? other$actedName != null : !this$actedName.equals(other$actedName)) return false;
final Object this$action = this.getAction();
final Object other$action = other.getAction();
return this$action == null ? other$action == null : this$action.equals(other$action);
}
@Override
public int hashCode() {
final int PRIME = 59;
int result = 1;
final long $timestamp = this.getTimestamp();
result = result * PRIME + (int) ($timestamp >>> 32 ^ $timestamp);
final Object $actor = this.getActor();
result = result * PRIME + ($actor == null ? 43 : $actor.hashCode());
final Object $actorName = this.getActorName();
result = result * PRIME + ($actorName == null ? 43 : $actorName.hashCode());
result = result * PRIME + this.getType();
final Object $acted = this.getActed();
result = result * PRIME + ($acted == null ? 43 : $acted.hashCode());
final Object $actedName = this.getActedName();
result = result * PRIME + ($actedName == null ? 43 : $actedName.hashCode());
final Object $action = this.getAction();
result = result * PRIME + ($action == null ? 43 : $action.hashCode());
return result;
}
public static class LogEntryBuilder extends AbstractLogEntryBuilder<LogEntry, LogEntry.LogEntryBuilder> {
@Override
protected LogEntry createObj() {
return new LogEntry();
}
@Override
protected LogEntryBuilder getThis() {
return this;
}
}
public static abstract class AbstractLogEntryBuilder<T extends LogEntry, B extends AbstractLogEntryBuilder<T, B>> {
private T obj;
private B thisObj;
public AbstractLogEntryBuilder() {
obj = createObj();
thisObj = getThis();
}
protected abstract T createObj();
protected abstract B getThis();
public long getTimestamp() {
return obj.getTimestamp();
}
public UUID getActor() {
return obj.getActor();
}
public String getActorName() {
return obj.getActorName();
}
public char getType() {
return obj.getType();
}
public UUID getActed() {
return obj.getActed();
}
public String getActedName() {
return obj.getActedName();
}
public String getAction() {
return obj.getAction();
}
public B timestamp(long timestamp) {
obj.setTimestamp(timestamp);
return thisObj;
}
public B actor(UUID actor) {
obj.setActor(actor);
return thisObj;
}
public B actorName(String actorName) {
obj.setActorName(actorName);
return thisObj;
}
public B type(char type) {
obj.setType(type);
return thisObj;
}
public B acted(UUID acted) {
obj.setActed(acted);
return thisObj;
}
public B actedName(String actedName) {
obj.setActedName(actedName);
return thisObj;
}
public B action(String action) {
obj.setAction(action);
return thisObj;
}
public T build() {
if (getActor() == null) {
throw new NullPointerException("actor");
}
if (getActorName() == null) {
throw new NullPointerException("actorName");
}
if (getActedName() == null) {
throw new NullPointerException("actedName");
}
if (getAction() == null) {
throw new NullPointerException("action");
}
return obj;
}
@Override
public String toString() {
return "LogEntry.LogEntryBuilder(timestamp=" + getTimestamp() + ", actor=" + getActor() + ", actorName=" +
getActorName() + ", type=" + getType() + ", acted=" + getActed() + ", actedName=" + getActedName() +
", action=" + getAction() + ")";
}
}
}
@@ -22,6 +22,8 @@
package me.lucko.luckperms.api;
import me.lucko.luckperms.api.event.LPListener;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
@@ -42,6 +44,18 @@ public interface LuckPermsApi {
*/
String getVersion();
/**
* Registers a listener to be sent LuckPerms events
* @param listener the listener instance
*/
void registerListener(LPListener listener);
/**
* Unregisters a previously registered listener from the EventBus
* @param listener the listener instance to unregister
*/
void unregisterListener(LPListener listener);
/**
* Gets a wrapped {@link LPConfiguration} instance, with read only access
* @return a configuration instance
@@ -22,8 +22,6 @@
package me.lucko.luckperms.api.data;
import lombok.NonNull;
import java.util.function.Consumer;
public interface Callback<T> {
@@ -34,11 +32,17 @@ public interface Callback<T> {
return t -> {};
}
static <T> Callback<T> of(@NonNull Runnable runnable) {
static <T> Callback<T> of(Runnable runnable) {
if (runnable == null) {
throw new NullPointerException("runnable");
}
return t -> runnable.run();
}
static <T> Callback<T> of(@NonNull Consumer<T> consumer) {
static <T> Callback<T> of(Consumer<T> consumer) {
if (consumer == null) {
throw new NullPointerException("consumer");
}
return consumer::accept;
}
@@ -0,0 +1,33 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.api.data;
@SuppressWarnings("deprecation")
public interface DatastoreConfiguration extends MySQLConfiguration {
String getAddress();
String getDatabase();
String getUsername();
String getPassword();
}
@@ -22,6 +22,10 @@
package me.lucko.luckperms.api.data;
/**
* @deprecated Use {@link DatastoreConfiguration}. This is now used by multiple datastores, not just MySQL.
*/
@Deprecated
public interface MySQLConfiguration {
String getAddress();
@@ -0,0 +1,57 @@
/*
* 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.event;
import me.lucko.luckperms.api.PermissionHolder;
import java.util.Optional;
public class AbstractPermissionAddEvent extends TargetedEvent<PermissionHolder> {
private final String server;
private final String world;
private final long expiry;
protected AbstractPermissionAddEvent(String eventName, PermissionHolder target, String server, String world, long expiry) {
super(eventName, target);
this.server = server;
this.world = world;
this.expiry = expiry;
}
public Optional<String> getServer() {
return Optional.ofNullable(server);
}
public Optional<String> getWorld() {
return Optional.ofNullable(world);
}
public boolean isTemporary() {
return expiry != 0L;
}
public long getExpiry() {
return expiry;
}
}
@@ -0,0 +1,54 @@
/*
* 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.event;
import me.lucko.luckperms.api.PermissionHolder;
import java.util.Optional;
public class AbstractPermissionRemoveEvent extends TargetedEvent<PermissionHolder> {
private final String server;
private final String world;
private final boolean temporary;
protected AbstractPermissionRemoveEvent(String eventName, PermissionHolder target, String server, String world, boolean temporary) {
super(eventName, target);
this.server = server;
this.world = world;
this.temporary = temporary;
}
public Optional<String> getServer() {
return Optional.ofNullable(server);
}
public Optional<String> getWorld() {
return Optional.ofNullable(world);
}
public boolean getTemporary() {
return temporary;
}
}
@@ -0,0 +1,40 @@
/*
* 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.event;
public class CancellableEvent extends LPEvent {
private boolean cancelled = false;
protected CancellableEvent(String eventName) {
super(eventName);
}
public boolean isCancelled() {
return cancelled;
}
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
}
@@ -0,0 +1,58 @@
/*
* 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.event;
import me.lucko.luckperms.api.LuckPermsApi;
public abstract class LPEvent {
/**
* A link to the API instance provided for convenience.
*/
private LuckPermsApi api = null;
/**
* A friendly name of the event
*/
private final String eventName;
protected LPEvent(String eventName) {
this.eventName = eventName;
}
public String getEventName() {
return eventName;
}
public LuckPermsApi getApi() {
return api;
}
public void setApi(LuckPermsApi api) {
if (this.api != null) {
throw new IllegalStateException("API can only be set once.");
}
this.api = api;
}
}
@@ -0,0 +1,29 @@
/*
* 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.event;
/**
* Used to mark a class that listens for LuckPerms events
*/
public interface LPListener {
}
@@ -0,0 +1,37 @@
/*
* 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.event;
public class TargetedEvent<T> extends LPEvent {
private final T target;
protected TargetedEvent(String eventName, T target) {
super(eventName);
this.target = target;
}
public T getTarget() {
return target;
}
}
@@ -0,0 +1,58 @@
/*
* 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.event;
import me.lucko.luckperms.api.Track;
import me.lucko.luckperms.api.User;
public abstract class TrackEvent extends LPEvent {
private final Track track;
private final User user;
private final String fromGroup;
private final String toGroup;
protected TrackEvent(String eventName, Track track, User user, String fromGroup, String toGroup) {
super(eventName);
this.track = track;
this.user = user;
this.fromGroup = fromGroup;
this.toGroup = toGroup;
}
public Track getTrack() {
return track;
}
public User getUser() {
return user;
}
public String getFromGroup() {
return fromGroup;
}
public String getToGroup() {
return toGroup;
}
}
@@ -0,0 +1,39 @@
/*
* 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.event;
import me.lucko.luckperms.api.User;
public class UserEvent extends LPEvent {
private final User user;
protected UserEvent(String eventName, User user) {
super(eventName);
this.user = user;
}
public User getUser() {
return user;
}
}
@@ -0,0 +1,41 @@
/*
* 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.event.events;
import me.lucko.luckperms.api.Group;
import me.lucko.luckperms.api.PermissionHolder;
import me.lucko.luckperms.api.event.AbstractPermissionAddEvent;
public class GroupAddEvent extends AbstractPermissionAddEvent {
private final Group group;
public GroupAddEvent(PermissionHolder target, Group group, String server, String world, long expiry) {
super("Group Add Event", target, server, world, expiry);
this.group = group;
}
public Group getGroup() {
return group;
}
}
@@ -0,0 +1,40 @@
/*
* 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.event.events;
import me.lucko.luckperms.api.PermissionHolder;
import me.lucko.luckperms.api.event.AbstractPermissionRemoveEvent;
public class GroupRemoveEvent extends AbstractPermissionRemoveEvent {
private final String group;
public GroupRemoveEvent(PermissionHolder target, String group, String server, String world, boolean temporary) {
super("Group Remove Event", target, server, world, temporary);
this.group = group;
}
public String getGroup() {
return group;
}
}
@@ -0,0 +1,41 @@
/*
* 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.event.events;
import me.lucko.luckperms.api.LogEntry;
import me.lucko.luckperms.api.event.CancellableEvent;
public class LogNotifyEvent extends CancellableEvent {
private final LogEntry entry;
public LogNotifyEvent(LogEntry entry) {
super("Log Notify Event");
this.entry = entry;
}
public LogEntry getEntry() {
return entry;
}
}
@@ -0,0 +1,40 @@
/*
* 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.event.events;
import me.lucko.luckperms.api.PermissionHolder;
import me.lucko.luckperms.api.event.TargetedEvent;
public class PermissionExpireEvent extends TargetedEvent<PermissionHolder> {
private final String node;
public PermissionExpireEvent(PermissionHolder target, String node) {
super("Permission Expire Event", target);
this.node = node;
}
public String getNode() {
return node;
}
}
@@ -0,0 +1,53 @@
/*
* 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.event.events;
import me.lucko.luckperms.api.PermissionHolder;
import me.lucko.luckperms.api.event.AbstractPermissionAddEvent;
import java.util.AbstractMap;
import java.util.Map;
public class PermissionSetEvent extends AbstractPermissionAddEvent {
private final String node;
private final boolean value;
public PermissionSetEvent(PermissionHolder target, String node, boolean value, String server, String world, long expiry) {
super("Permission Set Event", target, server, world, expiry);
this.node = node;
this.value = value;
}
public String getNode() {
return node;
}
public boolean getValue() {
return value;
}
public Map.Entry<String, Boolean> getEntry() {
return new AbstractMap.SimpleEntry<>(node, value);
}
}
@@ -0,0 +1,40 @@
/*
* 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.event.events;
import me.lucko.luckperms.api.PermissionHolder;
import me.lucko.luckperms.api.event.AbstractPermissionRemoveEvent;
public class PermissionUnsetEvent extends AbstractPermissionRemoveEvent {
private final String node;
public PermissionUnsetEvent(PermissionHolder target, String node, String server, String world, boolean temporary) {
super("Permission Unset Event", target, server, world, temporary);
this.node = node;
}
public String getNode() {
return node;
}
}
@@ -0,0 +1,33 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.events;
import me.lucko.luckperms.api.event.LPEvent;
public class PostSyncEvent extends LPEvent {
public PostSyncEvent() {
super("Post Sync Event");
}
}
@@ -0,0 +1,33 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.api.event.events;
import me.lucko.luckperms.api.event.CancellableEvent;
public class PreSyncEvent extends CancellableEvent {
public PreSyncEvent() {
super("Pre Sync Event");
}
}
@@ -0,0 +1,35 @@
/*
* 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.event.events;
import me.lucko.luckperms.api.Track;
import me.lucko.luckperms.api.User;
import me.lucko.luckperms.api.event.TrackEvent;
public class UserDemoteEvent extends TrackEvent {
public UserDemoteEvent(Track track, User user, String from, String to) {
super("User Demote Event", track, user, from, to);
}
}
@@ -0,0 +1,51 @@
/*
* 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.event.events;
import me.lucko.luckperms.api.event.LPEvent;
import java.util.UUID;
/**
* This event is fired before the player has actually joined the game on the async login / auth event.
* If you want to do something with the user, store the UUID in a set, and then check the set in the PlayerJoinEvent o.e.
*/
public class UserFirstLoginEvent extends LPEvent {
private final UUID uuid;
private final String username;
public UserFirstLoginEvent(UUID uuid, String username) {
super("User First Join Event");
this.uuid = uuid;
this.username = username;
}
public UUID getUuid() {
return uuid;
}
public String getUsername() {
return username;
}
}
@@ -0,0 +1,34 @@
/*
* 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.event.events;
import me.lucko.luckperms.api.User;
import me.lucko.luckperms.api.event.UserEvent;
public class UserPermissionRefreshEvent extends UserEvent {
public UserPermissionRefreshEvent(User user) {
super("User Permission Refresh Event", user);
}
}
@@ -0,0 +1,35 @@
/*
* 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.event.events;
import me.lucko.luckperms.api.Track;
import me.lucko.luckperms.api.User;
import me.lucko.luckperms.api.event.TrackEvent;
public class UserPromoteEvent extends TrackEvent {
public UserPromoteEvent(Track track, User user, String from, String to) {
super("User Promote Event", track, user, from, to);
}
}
+25 -15
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId>
<version>2.3</version>
<version>2.5-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -14,7 +14,7 @@
<build>
<defaultGoal>clean package</defaultGoal>
<finalName>LuckPerms-${project.version}.${git.closest.tag.commit.count}</finalName>
<finalName>LuckPerms-${release.version}.${git.closest.tag.commit.count}</finalName>
<sourceDirectory>${basedir}/src/main/java</sourceDirectory>
<resources>
<resource>
@@ -43,7 +43,12 @@
<goal>shade</goal>
</goals>
<configuration>
<minimizeJar>true</minimizeJar>
<minimizeJar>false</minimizeJar>
<artifactSet>
<excludes>
<exclude>org.xerial:*</exclude>
</excludes>
</artifactSet>
<relocations>
<relocation>
<pattern>org.slf4j</pattern>
@@ -53,6 +58,18 @@
<pattern>com.zaxxer.hikari</pattern>
<shadedPattern>me.lucko.luckperms.lib.hikari</shadedPattern>
</relocation>
<relocation>
<pattern>com.mongodb</pattern>
<shadedPattern>me.lucko.luckperms.lib.mongodb</shadedPattern>
</relocation>
<relocation>
<pattern>org.bson</pattern>
<shadedPattern>me.lucko.luckperms.lib.bson</shadedPattern>
</relocation>
<relocation>
<pattern>org.h2</pattern>
<shadedPattern>me.lucko.luckperms.lib.h2</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
@@ -105,19 +122,12 @@
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<!-- HikariCP -->
<!-- Lombok -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>2.4.7</version>
<scope>compile</scope>
</dependency>
<!-- slf4j library -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.9</version>
<scope>compile</scope>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
@@ -31,12 +31,12 @@ import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.core.LPConfiguration;
import me.lucko.luckperms.core.UuidCache;
import me.lucko.luckperms.data.Importer;
import me.lucko.luckperms.groups.GroupManager;
import me.lucko.luckperms.runnables.ExpireTemporaryTask;
import me.lucko.luckperms.runnables.UpdateTask;
import me.lucko.luckperms.storage.Datastore;
import me.lucko.luckperms.storage.methods.FlatfileDatastore;
import me.lucko.luckperms.storage.methods.MySQLDatastore;
import me.lucko.luckperms.storage.methods.SQLiteDatastore;
import me.lucko.luckperms.storage.StorageFactory;
import me.lucko.luckperms.tracks.TrackManager;
import me.lucko.luckperms.users.BukkitUserManager;
import me.lucko.luckperms.users.UserManager;
@@ -60,7 +60,9 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
private TrackManager trackManager;
private Datastore datastore;
private UuidCache uuidCache;
private ApiProvider apiProvider;
private Logger log;
private Importer importer;
@Override
public void onEnable() {
@@ -81,30 +83,14 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
main.setTabCompleter(commandManager);
main.setAliases(Arrays.asList("perms", "lp", "permissions", "p", "perm"));
getLog().info("Detecting storage method...");
final String storageMethod = configuration.getStorageMethod();
if (storageMethod.equalsIgnoreCase("mysql")) {
getLog().info("Using MySQL as storage method.");
datastore = new MySQLDatastore(this, configuration.getDatabaseValues());
} else if (storageMethod.equalsIgnoreCase("sqlite")) {
getLog().info("Using SQLite as storage method.");
datastore = new SQLiteDatastore(this, new File(getDataFolder(), "luckperms.sqlite"));
} else if (storageMethod.equalsIgnoreCase("flatfile")) {
getLog().info("Using Flatfile (JSON) as storage method.");
datastore = new FlatfileDatastore(this, getDataFolder());
} else {
getLog().severe("Storage method '" + storageMethod + "' was not recognised. Using SQLite as fallback.");
datastore = new SQLiteDatastore(this, new File(getDataFolder(), "luckperms.sqlite"));
}
getLog().info("Initialising datastore...");
datastore.init();
datastore = StorageFactory.getDatastore(this, "h2");
getLog().info("Loading internal permission managers...");
uuidCache = new UuidCache(getConfiguration().getOnlineMode());
userManager = new BukkitUserManager(this);
groupManager = new GroupManager(this);
trackManager = new TrackManager();
importer = new Importer(commandManager);
// Run update task to refresh any online users
getLog().info("Scheduling Update Task to refresh any online users.");
@@ -121,6 +107,7 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
}
getServer().getScheduler().runTaskTimer(this, BukkitSenderFactory.get(), 1L, 1L);
getServer().getScheduler().runTaskTimerAsynchronously(this, new ExpireTemporaryTask(this), 60L, 60L);
// Provide vault support
getLog().info("Attempting to hook into Vault...");
@@ -137,9 +124,9 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
}
getLog().info("Registering API...");
final ApiProvider provider = new ApiProvider(this);
LuckPerms.registerProvider(provider);
getServer().getServicesManager().register(LuckPermsApi.class, provider, this, ServicePriority.Normal);
apiProvider = new ApiProvider(this);
LuckPerms.registerProvider(apiProvider);
getServer().getServicesManager().register(LuckPermsApi.class, apiProvider, this, ServicePriority.Normal);
getLog().info("Successfully loaded.");
}
@@ -169,6 +156,11 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
return getDescription().getVersion();
}
@Override
public File getMainDir() {
return getDataFolder();
}
@Override
public Message getPlayerStatus(UUID uuid) {
return getServer().getPlayer(getUuidCache().getExternalUUID(uuid)) != null ? Message.PLAYER_ONLINE : Message.PLAYER_OFFLINE;
@@ -189,6 +181,11 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
return getServer().getOnlinePlayers().stream().map(p -> BukkitSenderFactory.get().wrap(p)).collect(Collectors.toList());
}
@Override
public Sender getConsoleSender() {
return BukkitSenderFactory.get().wrap(getServer().getConsoleSender());
}
@Override
public List<String> getPossiblePermissions() {
final List<String> perms = new ArrayList<>();
@@ -25,6 +25,8 @@ package me.lucko.luckperms.users;
import lombok.Getter;
import lombok.Setter;
import me.lucko.luckperms.LPBukkitPlugin;
import me.lucko.luckperms.api.event.events.UserPermissionRefreshEvent;
import me.lucko.luckperms.api.implementation.internal.UserLink;
import org.bukkit.entity.Player;
import org.bukkit.permissions.PermissionAttachment;
@@ -104,6 +106,8 @@ public class BukkitUser extends User {
} catch (Exception e) {
e.printStackTrace();
}
plugin.getApiProvider().fireEventAsync(new UserPermissionRefreshEvent(new UserLink(this)));
});
}
}
+13 -5
View File
@@ -1,4 +1,9 @@
# LuckPerms Configuration
##############################################################################
# +------------------------------------------------------------------------+ #
# | LuckPerms Configuration | #
# | https://github.com/lucko/LuckPerms | #
# +------------------------------------------------------------------------+ #
##############################################################################
# The name of the server, used for server specific permissions. Set to 'global' to disable.
server: global
@@ -38,13 +43,16 @@ apply-regex: true
apply-shorthand: true
# Which storage method the plugin should use.
# Currently supported: mysql, sqlite, flatfile
# Fill out connection info below if you're using MySQL
storage-method: sqlite
# Currently supported: mysql, sqlite, h2, flatfile, mongodb
# Fill out connection info below if you're using MySQL or MongoDB
storage-method: h2
sql:
data:
address: localhost:3306
database: minecraft
username: root
password: ''
# Set to -1 to disable. If this is the only instance accessing the datastore, you can disable syncing.
# e.g. if you're using sqlite or flatfile, this can be set to -1 to save resources.
sync-minutes: 3
+2 -1
View File
@@ -1,6 +1,6 @@
name: LuckPerms
author: Luck
version: ${project.version}.${git.closest.tag.commit.count}
version: ${release.version}.${git.closest.tag.commit.count}
main: me.lucko.luckperms.LPBukkitPlugin
softdepend: [Vault]
description: A permissions plugin
@@ -15,6 +15,7 @@ permissions:
luckperms.sync: true
luckperms.info: true
luckperms.debug: true
luckperms.import: true
luckperms.creategroup: true
luckperms.deletegroup: true
luckperms.listgroups: true
+20 -15
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId>
<version>2.3</version>
<version>2.5-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -14,7 +14,7 @@
<build>
<defaultGoal>clean package</defaultGoal>
<finalName>LuckPermsBungee-${project.version}.${git.closest.tag.commit.count}</finalName>
<finalName>LuckPermsBungee-${release.version}.${git.closest.tag.commit.count}</finalName>
<sourceDirectory>${basedir}/src/main/java</sourceDirectory>
<resources>
<resource>
@@ -43,7 +43,7 @@
<goal>shade</goal>
</goals>
<configuration>
<minimizeJar>true</minimizeJar>
<minimizeJar>false</minimizeJar>
<relocations>
<relocation>
<pattern>org.slf4j</pattern>
@@ -53,6 +53,18 @@
<pattern>com.zaxxer.hikari</pattern>
<shadedPattern>me.lucko.luckperms.lib.hikari</shadedPattern>
</relocation>
<relocation>
<pattern>com.mongodb</pattern>
<shadedPattern>me.lucko.luckperms.lib.mongodb</shadedPattern>
</relocation>
<relocation>
<pattern>org.bson</pattern>
<shadedPattern>me.lucko.luckperms.lib.bson</shadedPattern>
</relocation>
<relocation>
<pattern>org.h2</pattern>
<shadedPattern>me.lucko.luckperms.lib.h2</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
@@ -98,19 +110,12 @@
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<!-- HikariCP -->
<!-- Lombok -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>2.4.7</version>
<scope>compile</scope>
</dependency>
<!-- slf4j library -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.9</version>
<scope>compile</scope>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
<scope>provided</scope>
</dependency>
</dependencies>
@@ -39,7 +39,8 @@ import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
class BungeeListener extends AbstractListener implements Listener {
@SuppressWarnings("WeakerAccess")
public class BungeeListener extends AbstractListener implements Listener {
private static final TextComponent WARN_MESSAGE = new TextComponent(Message.LOADING_ERROR.toString());
private final LPBungeePlugin plugin;
@@ -30,11 +30,12 @@ import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.core.LPConfiguration;
import me.lucko.luckperms.core.UuidCache;
import me.lucko.luckperms.data.Importer;
import me.lucko.luckperms.groups.GroupManager;
import me.lucko.luckperms.runnables.ExpireTemporaryTask;
import me.lucko.luckperms.runnables.UpdateTask;
import me.lucko.luckperms.storage.Datastore;
import me.lucko.luckperms.storage.methods.FlatfileDatastore;
import me.lucko.luckperms.storage.methods.MySQLDatastore;
import me.lucko.luckperms.storage.StorageFactory;
import me.lucko.luckperms.tracks.TrackManager;
import me.lucko.luckperms.users.BungeeUserManager;
import me.lucko.luckperms.users.UserManager;
@@ -42,6 +43,7 @@ import me.lucko.luckperms.utils.LogFactory;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Plugin;
import java.io.File;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@@ -55,7 +57,9 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
private TrackManager trackManager;
private Datastore datastore;
private UuidCache uuidCache;
private ApiProvider apiProvider;
private Logger log;
private Importer importer;
@Override
public void onEnable() {
@@ -69,32 +73,20 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
// register commands
getLog().info("Registering commands...");
getProxy().getPluginManager().registerCommand(this, new BungeeCommand(new CommandManager(this)));
CommandManager commandManager = new CommandManager(this);
getProxy().getPluginManager().registerCommand(this, new BungeeCommand(commandManager));
// disable the default Bungee /perms command so it gets handled by the Bukkit plugin
getProxy().getDisabledCommands().add("perms");
getLog().info("Detecting storage method...");
final String storageMethod = configuration.getStorageMethod();
if (storageMethod.equalsIgnoreCase("mysql")) {
getLog().info("Using MySQL as storage method.");
datastore = new MySQLDatastore(this, configuration.getDatabaseValues());
} else if (storageMethod.equalsIgnoreCase("flatfile")) {
getLog().info("Using Flatfile (JSON) as storage method.");
datastore = new FlatfileDatastore(this, getDataFolder());
} else {
getLog().severe("Storage method '" + storageMethod + "' was not recognised. Using Flatfile as fallback.");
datastore = new FlatfileDatastore(this, getDataFolder());
}
getLog().info("Initialising datastore...");
datastore.init();
datastore = StorageFactory.getDatastore(this, "h2");
getLog().info("Loading internal permission managers...");
uuidCache = new UuidCache(getConfiguration().getOnlineMode());
userManager = new BungeeUserManager(this);
groupManager = new GroupManager(this);
trackManager = new TrackManager();
importer = new Importer(commandManager);
// Run update task to refresh any online users
getLog().info("Scheduling Update Task to refresh any online users.");
@@ -111,9 +103,11 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
// 20 times per second (once per "tick")
getProxy().getScheduler().schedule(this, BungeeSenderFactory.get(), 50L, 50L, TimeUnit.MILLISECONDS);
getProxy().getScheduler().schedule(this, new ExpireTemporaryTask(this), 3L, 3L, TimeUnit.SECONDS);
getLog().info("Registering API...");
LuckPerms.registerProvider(new ApiProvider(this));
apiProvider = new ApiProvider(this);
LuckPerms.registerProvider(apiProvider);
getLog().info("Successfully loaded.");
}
@@ -132,6 +126,11 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
return getDescription().getVersion();
}
@Override
public File getMainDir() {
return getDataFolder();
}
@Override
public Message getPlayerStatus(UUID uuid) {
return getProxy().getPlayer(getUuidCache().getExternalUUID(uuid)) != null ? Message.PLAYER_ONLINE : Message.PLAYER_OFFLINE;
@@ -152,6 +151,11 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
return getProxy().getPlayers().stream().map(p -> BungeeSenderFactory.get().wrap(p)).collect(Collectors.toList());
}
@Override
public Sender getConsoleSender() {
return BungeeSenderFactory.get().wrap(getProxy().getConsole());
}
@Override
public List<String> getPossiblePermissions() {
// No such thing on Bungee. Wildcards are processed in the listener instead.
+13 -5
View File
@@ -1,4 +1,9 @@
# LuckPerms Configuration
##############################################################################
# +------------------------------------------------------------------------+ #
# | LuckPerms Configuration | #
# | https://github.com/lucko/LuckPerms | #
# +------------------------------------------------------------------------+ #
##############################################################################
# The name of the server, used for server specific permissions. Set to 'global' to disable.
server: bungee
@@ -38,13 +43,16 @@ apply-regex: true
apply-shorthand: true
# Which storage method the plugin should use.
# Currently supported: mysql & flatfile
# Fill out connection info below if you're using MySQL
storage-method: flatfile
# Currently supported: mysql, sqlite, h2, flatfile, mongodb
# Fill out connection info below if you're using MySQL or MongoDB
storage-method: h2
sql:
data:
address: localhost:3306
database: minecraft
username: root
password: ''
# Set to -1 to disable. If this is the only instance accessing the datastore, you can disable syncing.
# e.g. if you're using sqlite or flatfile, this can be set to -1 to save resources.
sync-minutes: 3
+1 -1
View File
@@ -1,5 +1,5 @@
name: LuckPerms
author: Luck
version: ${project.version}.${git.closest.tag.commit.count}
version: ${release.version}.${git.closest.tag.commit.count}
main: me.lucko.luckperms.LPBungeePlugin
description: A permissions plugin
+29 -1
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId>
<version>2.3</version>
<version>2.5-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -39,6 +39,27 @@
<version>2.4.7</version>
<scope>compile</scope>
</dependency>
<!-- SQLite -->
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.8.11.2</version>
<scope>compile</scope>
</dependency>
<!-- H2 -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.192</version>
<scope>compile</scope>
</dependency>
<!-- MongoDB -->
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.3.0</version>
<scope>compile</scope>
</dependency>
<!-- slf4j library -->
<dependency>
<groupId>org.slf4j</groupId>
@@ -60,6 +81,13 @@
<version>19.0</version>
<scope>provided</scope>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
@@ -23,15 +23,18 @@
package me.lucko.luckperms;
import me.lucko.luckperms.api.Logger;
import me.lucko.luckperms.api.implementation.ApiProvider;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.core.LPConfiguration;
import me.lucko.luckperms.core.UuidCache;
import me.lucko.luckperms.data.Importer;
import me.lucko.luckperms.groups.GroupManager;
import me.lucko.luckperms.storage.Datastore;
import me.lucko.luckperms.tracks.TrackManager;
import me.lucko.luckperms.users.UserManager;
import java.io.File;
import java.util.List;
import java.util.Set;
import java.util.UUID;
@@ -42,53 +45,34 @@ import java.util.UUID;
*/
public interface LuckPermsPlugin {
/**
* Retrieves the {@link UserManager} used to manage users and their permissions/groups
* @return the {@link UserManager} instance
/*
* Access to all of the main internal manager classes
*/
UserManager getUserManager();
/**
* Retrieves the {@link GroupManager} used to manage the loaded groups and modify their permissions
* @return the {@link GroupManager} instance
*/
GroupManager getGroupManager();
/**
* Retrieves the {@link TrackManager} used to manage the loaded tracks
* @return the {@link TrackManager} instance
*/
TrackManager getTrackManager();
/**
* Retrieves the {@link LPConfiguration} for getting values from the config
* @return the {@link LPConfiguration} implementation for the platform
*/
LPConfiguration getConfiguration();
/**
* Retrieves the {@link Datastore} for loading/saving plugin data
* @return the {@link Datastore} object
*/
Datastore getDatastore();
/**
* Retrieves the {@link Logger} for the plugin
* @return the plugin's {@link Logger}
*/
Logger getLog();
/**
* Retrieves the {@link UuidCache} for the plugin
* @return the plugin's {@link UuidCache}
*/
UuidCache getUuidCache();
ApiProvider getApiProvider();
Importer getImporter();
/**
* @return the version of the plugin
*/
String getVersion();
/**
* @return the main plugin directory
*/
File getMainDir();
/**
* @return the platforms data folder
*/
File getDataFolder();
/**
* Returns a colored string indicating the status of a player
* @param uuid The player's uuid
@@ -109,11 +93,15 @@ public interface LuckPermsPlugin {
List<String> getPlayerList();
/**
* Gets a list of all Senders online on the platform
* @return a {@link List} of senders
* @return a {@link List} of senders online on the platform
*/
List<Sender> getSenders();
/**
* @return the console sender of the instance
*/
Sender getConsoleSender();
/**
* Gets all possible permission nodes, used for resolving wildcards
* @return a {@link List} of permission nodes
@@ -22,10 +22,13 @@
package me.lucko.luckperms.api.implementation;
import com.google.common.eventbus.EventBus;
import lombok.AllArgsConstructor;
import lombok.NonNull;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.api.*;
import me.lucko.luckperms.api.event.LPEvent;
import me.lucko.luckperms.api.event.LPListener;
import me.lucko.luckperms.api.implementation.internal.*;
import java.util.Optional;
@@ -39,6 +42,21 @@ import java.util.stream.Collectors;
@AllArgsConstructor
public class ApiProvider implements LuckPermsApi {
private final LuckPermsPlugin plugin;
private final EventBus eventBus = new EventBus("LuckPerms");
public void fireEventAsync(LPEvent event) {
plugin.doAsync(() -> fireEvent(event));
}
public void fireEvent(LPEvent event) {
try {
event.setApi(this);
eventBus.post(event);
} catch (Exception e) {
getLogger().severe("Couldn't fire LuckPerms Event: " + event.getEventName());
e.printStackTrace();
}
}
@Override
public void runUpdateTask() {
@@ -50,6 +68,16 @@ public class ApiProvider implements LuckPermsApi {
return plugin.getVersion();
}
@Override
public void registerListener(LPListener listener) {
eventBus.register(listener);
}
@Override
public void unregisterListener(LPListener listener) {
eventBus.unregister(listener);
}
@Override
public LPConfiguration getConfiguration() {
return new LPConfigurationLink(plugin.getConfiguration());
@@ -24,6 +24,7 @@ package me.lucko.luckperms.api.implementation.internal;
import lombok.AllArgsConstructor;
import me.lucko.luckperms.api.LPConfiguration;
import me.lucko.luckperms.api.data.DatastoreConfiguration;
import me.lucko.luckperms.api.data.MySQLConfiguration;
/**
@@ -78,8 +79,14 @@ public class LPConfigurationLink implements LPConfiguration {
return master.getApplyShorthand();
}
@SuppressWarnings("deprecation")
@Override
public MySQLConfiguration getDatabaseValues() {
return getDatastoreConfig();
}
@Override
public DatastoreConfiguration getDatastoreConfig() {
return master.getDatabaseValues();
}
@@ -22,7 +22,6 @@
package me.lucko.luckperms.api.implementation.internal;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.NonNull;
import me.lucko.luckperms.api.PermissionHolder;
@@ -39,8 +38,8 @@ import static me.lucko.luckperms.api.implementation.internal.Utils.*;
* Provides a link between {@link PermissionHolder} and {@link me.lucko.luckperms.core.PermissionHolder}
*/
@SuppressWarnings("unused")
@AllArgsConstructor(access = AccessLevel.PACKAGE)
class PermissionHolderLink implements PermissionHolder {
@AllArgsConstructor
public class PermissionHolderLink implements PermissionHolder {
@NonNull
private final me.lucko.luckperms.core.PermissionHolder master;
@@ -33,6 +33,7 @@ import me.lucko.luckperms.commands.group.GroupMainCommand;
import me.lucko.luckperms.commands.group.ListGroups;
import me.lucko.luckperms.commands.log.LogMainCommand;
import me.lucko.luckperms.commands.misc.DebugCommand;
import me.lucko.luckperms.commands.misc.ImportCommand;
import me.lucko.luckperms.commands.misc.InfoCommand;
import me.lucko.luckperms.commands.misc.SyncCommand;
import me.lucko.luckperms.commands.track.CreateTrack;
@@ -61,6 +62,7 @@ public class CommandManager {
.add(new SyncCommand())
.add(new InfoCommand())
.add(new DebugCommand())
.add(new ImportCommand())
.add(new CreateGroup())
.add(new DeleteGroup())
.add(new ListGroups())
@@ -144,18 +146,28 @@ public class CommandManager {
*/
@SuppressWarnings("unchecked")
public List<String> onTabComplete(Sender sender, List<String> args) {
final List<MainCommand> mains = mainCommands.stream().filter(m -> m.isAuthorized(sender)).collect(Collectors.toList());
final List<MainCommand> mains = mainCommands.stream()
.filter(m -> m.isAuthorized(sender))
.collect(Collectors.toList());
if (args.size() <= 1) {
if (args.isEmpty() || args.get(0).equalsIgnoreCase("")) {
return mains.stream().map(MainCommand::getName).map(String::toLowerCase).collect(Collectors.toList());
return mains.stream()
.map(m -> m.getName().toLowerCase())
.collect(Collectors.toList());
}
return mains.stream().map(MainCommand::getName).map(String::toLowerCase)
.filter(s -> s.startsWith(args.get(0).toLowerCase())).collect(Collectors.toList());
return mains.stream()
.map(m -> m.getName().toLowerCase())
.filter(s -> s.startsWith(args.get(0).toLowerCase()))
.collect(Collectors.toList());
}
Optional<MainCommand> o = mains.stream().filter(m -> m.getName().equalsIgnoreCase(args.get(0))).limit(1).findAny();
Optional<MainCommand> o = mains.stream()
.filter(m -> m.getName().equalsIgnoreCase(args.get(0)))
.limit(1)
.findAny();
if (!o.isPresent()) {
return Collections.emptyList();
}
@@ -76,7 +76,10 @@ public abstract class MainCommand<T> {
return CommandResult.INVALID_ARGS;
}
Optional<SubCommand<T>> o = subCommands.stream().filter(s -> s.getName().equalsIgnoreCase(args.get(requiredArgsLength - 1))).limit(1).findAny();
Optional<SubCommand<T>> o = subCommands.stream()
.filter(s -> s.getName().equalsIgnoreCase(args.get(requiredArgsLength - 1)))
.limit(1)
.findAny();
if (!o.isPresent()) {
Message.COMMAND_NOT_RECOGNISED.send(sender);
@@ -121,7 +124,7 @@ public abstract class MainCommand<T> {
protected abstract void cleanup(T t, LuckPermsPlugin plugin);
/**
* Get a list of objects for tab completion
* Get a list of {@link T} objects for tab completion
* @param plugin a link to the main plugin instance
* @return a list of strings
*/
@@ -138,7 +141,10 @@ public abstract class MainCommand<T> {
return;
}
List<SubCommand> subs = getSubCommands().stream().filter(s -> s.isAuthorized(sender)).collect(Collectors.toList());
List<SubCommand> subs = getSubCommands().stream()
.filter(s -> s.isAuthorized(sender))
.collect(Collectors.toList());
if (subs.size() > 0) {
Util.sendPluginMessage(sender, "&e" + getName() + " Sub Commands:");
@@ -168,20 +174,33 @@ public abstract class MainCommand<T> {
return objects;
}
return objects.stream().filter(s -> s.toLowerCase().startsWith(args.get(0).toLowerCase())).collect(Collectors.toList());
return objects.stream()
.filter(s -> s.toLowerCase().startsWith(args.get(0).toLowerCase()))
.collect(Collectors.toList());
}
final List<SubCommand<T>> subs = getSubCommands().stream().filter(s -> s.isAuthorized(sender)).collect(Collectors.toList());
final List<SubCommand<T>> subs = getSubCommands().stream()
.filter(s -> s.isAuthorized(sender))
.collect(Collectors.toList());
if (args.size() == 2) {
if (args.get(1).equalsIgnoreCase("")) {
return subs.stream().map(SubCommand::getName).map(String::toLowerCase).collect(Collectors.toList());
return subs.stream()
.map(m -> m.getName().toLowerCase())
.collect(Collectors.toList());
}
return subs.stream().map(SubCommand::getName).map(String::toLowerCase)
.filter(s -> s.toLowerCase().startsWith(args.get(1).toLowerCase())).collect(Collectors.toList());
return subs.stream()
.map(m -> m.getName().toLowerCase())
.filter(s -> s.toLowerCase().startsWith(args.get(1).toLowerCase()))
.collect(Collectors.toList());
}
Optional<SubCommand<T>> o = subs.stream().filter(s -> s.getName().equalsIgnoreCase(args.get(1))).limit(1).findAny();
Optional<SubCommand<T>> o = subs.stream()
.filter(s -> s.getName().equalsIgnoreCase(args.get(1)))
.limit(1)
.findAny();
if (!o.isPresent()) {
return Collections.emptyList();
}
@@ -147,36 +147,30 @@ public abstract class SubCommand<T> {
protected static void save(User user, Sender sender, LuckPermsPlugin plugin) {
user.refreshPermissions();
plugin.getDatastore().saveUser(user, success -> {
if (success) {
Message.USER_SAVE_SUCCESS.send(sender);
} else {
Message.USER_SAVE_ERROR.send(sender);
}
});
if (plugin.getDatastore().saveUser(user)) {
Message.USER_SAVE_SUCCESS.send(sender);
} else {
Message.USER_SAVE_ERROR.send(sender);
}
}
protected static void save(Group group, Sender sender, LuckPermsPlugin plugin) {
plugin.getDatastore().saveGroup(group, success -> {
if (success) {
Message.GROUP_SAVE_SUCCESS.send(sender);
} else {
Message.GROUP_SAVE_ERROR.send(sender);
}
if (plugin.getDatastore().saveGroup(group)) {
Message.GROUP_SAVE_SUCCESS.send(sender);
} else {
Message.GROUP_SAVE_ERROR.send(sender);
}
plugin.runUpdateTask();
});
plugin.runUpdateTask();
}
protected static void save(Track track, Sender sender, LuckPermsPlugin plugin) {
plugin.getDatastore().saveTrack(track, success -> {
if (success) {
Message.TRACK_SAVE_SUCCESS.send(sender);
} else {
Message.TRACK_SAVE_ERROR.send(sender);
}
if (plugin.getDatastore().saveTrack(track)) {
Message.TRACK_SAVE_SUCCESS.send(sender);
} else {
Message.TRACK_SAVE_ERROR.send(sender);
}
plugin.runUpdateTask();
});
plugin.runUpdateTask();
}
}
@@ -28,7 +28,7 @@ import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SingleMainCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntryBuilder;
import me.lucko.luckperms.data.LogEntry;
import me.lucko.luckperms.utils.ArgumentChecker;
import java.util.List;
@@ -62,7 +62,7 @@ public class CreateGroup extends SingleMainCommand {
}
Message.CREATE_SUCCESS.send(sender, groupName);
LogEntryBuilder.get().actor(sender).actedName(groupName).type('G').action("create").submit(plugin);
LogEntry.build().actor(sender).actedName(groupName).type('G').action("create").build().submit(plugin);
plugin.runUpdateTask();
return CommandResult.SUCCESS;
}
@@ -28,7 +28,7 @@ import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SingleMainCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntryBuilder;
import me.lucko.luckperms.data.LogEntry;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.utils.ArgumentChecker;
@@ -78,7 +78,7 @@ public class DeleteGroup extends SingleMainCommand {
}
Message.DELETE_SUCCESS.send(sender, groupName);
LogEntryBuilder.get().actor(sender).actedName(groupName).type('G').action("delete").submit(plugin);
LogEntry.build().actor(sender).actedName(groupName).type('G').action("delete").build().submit(plugin);
plugin.runUpdateTask();
return CommandResult.SUCCESS;
}
@@ -92,7 +92,8 @@ public class DeleteGroup extends SingleMainCommand {
return groups;
}
return groups.stream().filter(s -> s.toLowerCase().startsWith(args.get(0).toLowerCase())).collect(Collectors.toList());
return groups.stream().filter(s -> s.toLowerCase().startsWith(args.get(0).toLowerCase()))
.collect(Collectors.toList());
}
return Collections.emptyList();
@@ -29,7 +29,7 @@ import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntryBuilder;
import me.lucko.luckperms.data.LogEntry;
import me.lucko.luckperms.groups.Group;
import java.util.List;
@@ -44,7 +44,7 @@ public class GroupClear extends SubCommand<Group> {
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args, String label) {
group.clearNodes();
Message.CLEAR_SUCCESS.send(sender, group.getName());
LogEntryBuilder.get().actor(sender).acted(group).action("clear").submit(plugin);
LogEntry.build().actor(sender).acted(group).action("clear").build().submit(plugin);
save(group, sender, plugin);
return CommandResult.SUCCESS;
}
@@ -29,7 +29,7 @@ import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntryBuilder;
import me.lucko.luckperms.data.LogEntry;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.utils.ArgumentChecker;
@@ -74,24 +74,24 @@ public class GroupSetInherit extends SubCommand<Group> {
if (args.size() == 2) {
group.setInheritGroup(group1, server);
Message.GROUP_SETINHERIT_SERVER_SUCCESS.send(sender, group.getName(), group1.getName(), server);
LogEntryBuilder.get().actor(sender).acted(group)
LogEntry.build().actor(sender).acted(group)
.action("setinherit " + group1.getName() + " " + server)
.submit(plugin);
.build().submit(plugin);
} else {
final String world = args.get(2).toLowerCase();
group.setInheritGroup(group1, server, world);
Message.GROUP_SETINHERIT_SERVER_WORLD_SUCCESS.send(sender, group.getName(), group1.getName(), server, world);
LogEntryBuilder.get().actor(sender).acted(group)
LogEntry.build().actor(sender).acted(group)
.action("setinherit " + group1.getName() + " " + server + " " + world)
.submit(plugin);
.build().submit(plugin);
}
} else {
group.setInheritGroup(group1);
Message.GROUP_SETINHERIT_SUCCESS.send(sender, group.getName(), group1.getName());
LogEntryBuilder.get().actor(sender).acted(group)
LogEntry.build().actor(sender).acted(group)
.action("setinherit " + group1.getName())
.submit(plugin);
.build().submit(plugin);
}
save(group, sender, plugin);
@@ -30,7 +30,7 @@ import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Patterns;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntryBuilder;
import me.lucko.luckperms.data.LogEntry;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.utils.ArgumentChecker;
@@ -76,24 +76,24 @@ public class GroupSetPermission extends SubCommand<Group> {
if (args.size() == 3) {
group.setPermission(node, b, server);
Message.SETPERMISSION_SERVER_SUCCESS.send(sender, node, bool, group.getName(), server);
LogEntryBuilder.get().actor(sender).acted(group)
LogEntry.build().actor(sender).acted(group)
.action("set " + node + " " + b + " " + server)
.submit(plugin);
.build().submit(plugin);
} else {
final String world = args.get(3).toLowerCase();
group.setPermission(node, b, server, world);
Message.SETPERMISSION_SERVER_WORLD_SUCCESS.send(sender, node, bool, group.getName(), server, world);
LogEntryBuilder.get().actor(sender).acted(group)
LogEntry.build().actor(sender).acted(group)
.action("set " + node + " " + b + " " + server + " " + world)
.submit(plugin);
.build().submit(plugin);
}
} else {
group.setPermission(node, b);
Message.SETPERMISSION_SUCCESS.send(sender, node, bool, group.getName());
LogEntryBuilder.get().actor(sender).acted(group)
LogEntry.build().actor(sender).acted(group)
.action("set " + node + " " + b)
.submit(plugin);
.build().submit(plugin);
}
save(group, sender, plugin);
@@ -29,7 +29,7 @@ import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntryBuilder;
import me.lucko.luckperms.data.LogEntry;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.utils.ArgumentChecker;
@@ -55,10 +55,14 @@ public class GroupSetTempInherit extends SubCommand<Group> {
long duration;
try {
duration = DateUtil.parseDateDiff(args.get(1), true);
} catch (DateUtil.IllegalDateException e) {
Message.ILLEGAL_DATE_ERROR.send(sender, args.get(1));
return CommandResult.INVALID_ARGS;
duration = Long.parseLong(args.get(1));
} catch (NumberFormatException e) {
try {
duration = DateUtil.parseDateDiff(args.get(1), true);
} catch (DateUtil.IllegalDateException e1) {
Message.ILLEGAL_DATE_ERROR.send(sender, args.get(1));
return CommandResult.INVALID_ARGS;
}
}
if (DateUtil.shouldExpire(duration)) {
@@ -89,25 +93,25 @@ public class GroupSetTempInherit extends SubCommand<Group> {
group.setInheritGroup(group1, server, duration);
Message.GROUP_SET_TEMP_INHERIT_SERVER_SUCCESS.send(sender, group.getName(), group1.getName(), server,
DateUtil.formatDateDiff(duration));
LogEntryBuilder.get().actor(sender).acted(group)
LogEntry.build().actor(sender).acted(group)
.action("settempinherit " + group1.getName() + " " + duration + " " + server)
.submit(plugin);
.build().submit(plugin);
} else {
final String world = args.get(3).toLowerCase();
group.setInheritGroup(group1, server, world, duration);
Message.GROUP_SET_TEMP_INHERIT_SERVER_WORLD_SUCCESS.send(sender, group.getName(), group1.getName(), server,
world, DateUtil.formatDateDiff(duration));
LogEntryBuilder.get().actor(sender).acted(group)
LogEntry.build().actor(sender).acted(group)
.action("settempinherit " + group1.getName() + " " + duration + " " + server + " " + world)
.submit(plugin);
.build().submit(plugin);
}
} else {
group.setInheritGroup(group1, duration);
Message.GROUP_SET_TEMP_INHERIT_SUCCESS.send(sender, group.getName(), group1.getName(), DateUtil.formatDateDiff(duration));
LogEntryBuilder.get().actor(sender).acted(group)
LogEntry.build().actor(sender).acted(group)
.action("settempinherit " + group1.getName() + " " + duration)
.submit(plugin);
.build().submit(plugin);
}
save(group, sender, plugin);
@@ -30,7 +30,7 @@ import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Patterns;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntryBuilder;
import me.lucko.luckperms.data.LogEntry;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.utils.ArgumentChecker;
@@ -69,10 +69,14 @@ public class GroupSetTempPermission extends SubCommand<Group> {
long duration;
try {
duration = DateUtil.parseDateDiff(args.get(2), true);
} catch (DateUtil.IllegalDateException e) {
Message.ILLEGAL_DATE_ERROR.send(sender, args.get(2));
return CommandResult.INVALID_ARGS;
duration = Long.parseLong(args.get(2));
} catch (NumberFormatException e) {
try {
duration = DateUtil.parseDateDiff(args.get(2), true);
} catch (DateUtil.IllegalDateException e1) {
Message.ILLEGAL_DATE_ERROR.send(sender, args.get(2));
return CommandResult.INVALID_ARGS;
}
}
if (DateUtil.shouldExpire(duration)) {
@@ -92,25 +96,25 @@ public class GroupSetTempPermission extends SubCommand<Group> {
group.setPermission(node, b, server, duration);
Message.SETPERMISSION_TEMP_SERVER_SUCCESS.send(sender, node, bool, group.getName(), server,
DateUtil.formatDateDiff(duration));
LogEntryBuilder.get().actor(sender).acted(group)
LogEntry.build().actor(sender).acted(group)
.action("settemp " + node + " " + b + " " + duration + " " + server)
.submit(plugin);
.build().submit(plugin);
} else {
final String world = args.get(4).toLowerCase();
group.setPermission(node, b, server, world, duration);
Message.SETPERMISSION_TEMP_SERVER_WORLD_SUCCESS.send(sender, node, bool, group.getName(), server,
world, DateUtil.formatDateDiff(duration));
LogEntryBuilder.get().actor(sender).acted(group)
LogEntry.build().actor(sender).acted(group)
.action("settemp " + node + " " + b + " " + duration + " " + server + " " + world)
.submit(plugin);
.build().submit(plugin);
}
} else {
group.setPermission(node, b, duration);
Message.SETPERMISSION_TEMP_SUCCESS.send(sender, node, bool, group.getName(), DateUtil.formatDateDiff(duration));
LogEntryBuilder.get().actor(sender).acted(group)
LogEntry.build().actor(sender).acted(group)
.action("settemp " + node + " " + b + " " + duration)
.submit(plugin);
.build().submit(plugin);
}
save(group, sender, plugin);
@@ -30,7 +30,7 @@ import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Patterns;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntryBuilder;
import me.lucko.luckperms.data.LogEntry;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.utils.ArgumentChecker;
@@ -68,24 +68,24 @@ public class GroupUnSetPermission extends SubCommand<Group> {
if (args.size() == 2) {
group.unsetPermission(node, server);
Message.UNSETPERMISSION_SERVER_SUCCESS.send(sender, node, group.getName(), server);
LogEntryBuilder.get().actor(sender).acted(group)
LogEntry.build().actor(sender).acted(group)
.action("unset " + node + " " + server)
.submit(plugin);
.build().submit(plugin);
} else {
final String world = args.get(2).toLowerCase();
group.unsetPermission(node, server, world);
Message.UNSETPERMISSION_SERVER_WORLD_SUCCESS.send(sender, node, group.getName(), server, world);
LogEntryBuilder.get().actor(sender).acted(group)
LogEntry.build().actor(sender).acted(group)
.action("unset " + node + " " + server + " " + world)
.submit(plugin);
.build().submit(plugin);
}
} else {
group.unsetPermission(node);
Message.UNSETPERMISSION_SUCCESS.send(sender, node, group.getName());
LogEntryBuilder.get().actor(sender).acted(group)
LogEntry.build().actor(sender).acted(group)
.action("unset " + node)
.submit(plugin);
.build().submit(plugin);
}
save(group, sender, plugin);
@@ -29,7 +29,7 @@ import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntryBuilder;
import me.lucko.luckperms.data.LogEntry;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.utils.ArgumentChecker;
@@ -63,24 +63,24 @@ public class GroupUnsetInherit extends SubCommand<Group> {
if (args.size() == 2) {
group.unsetPermission("group." + groupName, server);
Message.GROUP_UNSETINHERIT_SERVER_SUCCESS.send(sender, group.getName(), groupName, server);
LogEntryBuilder.get().actor(sender).acted(group)
LogEntry.build().actor(sender).acted(group)
.action("unsetinherit " + groupName + " " + server)
.submit(plugin);
.build().submit(plugin);
} else {
final String world = args.get(2).toLowerCase();
group.unsetPermission("group." + groupName, server, world);
Message.GROUP_UNSETINHERIT_SERVER_WORLD_SUCCESS.send(sender, group.getName(), groupName, server, world);
LogEntryBuilder.get().actor(sender).acted(group)
LogEntry.build().actor(sender).acted(group)
.action("unsetinherit " + groupName + " " + server + " " + world)
.submit(plugin);
.build().submit(plugin);
}
} else {
group.unsetPermission("group." + groupName);
Message.GROUP_UNSETINHERIT_SUCCESS.send(sender, group.getName(), groupName);
LogEntryBuilder.get().actor(sender).acted(group)
LogEntry.build().actor(sender).acted(group)
.action("unsetinherit " + groupName)
.submit(plugin);
.build().submit(plugin);
}
save(group, sender, plugin);
@@ -29,7 +29,7 @@ import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntryBuilder;
import me.lucko.luckperms.data.LogEntry;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.utils.ArgumentChecker;
@@ -63,24 +63,24 @@ public class GroupUnsetTempInherit extends SubCommand<Group> {
if (args.size() == 2) {
group.unsetPermission("group." + groupName, server, true);
Message.GROUP_UNSET_TEMP_INHERIT_SERVER_SUCCESS.send(sender, group.getName(), groupName, server);
LogEntryBuilder.get().actor(sender).acted(group)
LogEntry.build().actor(sender).acted(group)
.action("unsettempinherit " + groupName + " " + server)
.submit(plugin);
.build().submit(plugin);
} else {
final String world = args.get(2).toLowerCase();
group.unsetPermission("group." + groupName, server, world, true);
Message.GROUP_UNSET_TEMP_INHERIT_SERVER_WORLD_SUCCESS.send(sender, group.getName(), groupName, server, world);
LogEntryBuilder.get().actor(sender).acted(group)
LogEntry.build().actor(sender).acted(group)
.action("unsettempinherit " + groupName + " " + server + " " + world)
.submit(plugin);
.build().submit(plugin);
}
} else {
group.unsetPermission("group." + groupName, true);
Message.GROUP_UNSET_TEMP_INHERIT_SUCCESS.send(sender, group.getName(), groupName);
LogEntryBuilder.get().actor(sender).acted(group)
LogEntry.build().actor(sender).acted(group)
.action("unsettempinherit " + groupName)
.submit(plugin);
.build().submit(plugin);
}
save(group, sender, plugin);
@@ -30,7 +30,7 @@ import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Patterns;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntryBuilder;
import me.lucko.luckperms.data.LogEntry;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.utils.ArgumentChecker;
@@ -69,24 +69,24 @@ public class GroupUnsetTempPermission extends SubCommand<Group> {
if (args.size() == 2) {
group.unsetPermission(node, server);
Message.UNSET_TEMP_PERMISSION_SERVER_SUCCESS.send(sender, node, group.getName(), server);
LogEntryBuilder.get().actor(sender).acted(group)
LogEntry.build().actor(sender).acted(group)
.action("unsettemp " + node + " " + server)
.submit(plugin);
.build().submit(plugin);
} else {
final String world = args.get(2).toLowerCase();
group.unsetPermission(node, server, world);
Message.UNSET_TEMP_PERMISSION_SERVER_WORLD_SUCCESS.send(sender, node, group.getName(), server, world);
LogEntryBuilder.get().actor(sender).acted(group)
LogEntry.build().actor(sender).acted(group)
.action("unsettemp " + node + " " + server + " " + world)
.submit(plugin);
.build().submit(plugin);
}
} else {
group.unsetPermission(node, true);
Message.UNSET_TEMP_PERMISSION_SUCCESS.send(sender, node, group.getName());
LogEntryBuilder.get().actor(sender).acted(group)
LogEntry.build().actor(sender).acted(group)
.action("unsettemp " + node)
.submit(plugin);
.build().submit(plugin);
}
save(group, sender, plugin);
@@ -42,7 +42,7 @@ public class LogMainCommand extends MainCommand<Log> {
.add(new LogRecent())
.add(new LogSearch())
.add(new LogNotify())
// .add(new LogExport())
.add(new LogExport())
.add(new LogUserHistory())
.add(new LogGroupHistory())
.add(new LogTrackHistory())
@@ -73,17 +73,28 @@ public class LogMainCommand extends MainCommand<Log> {
@Override
protected List<String> onTabComplete(Sender sender, List<String> args, LuckPermsPlugin plugin) {
final List<SubCommand<Log>> subs = getSubCommands().stream().filter(s -> s.isAuthorized(sender)).collect(Collectors.toList());
final List<SubCommand<Log>> subs = getSubCommands().stream()
.filter(s -> s.isAuthorized(sender))
.collect(Collectors.toList());
if (args.size() <= 1) {
if (args.isEmpty() || args.get(0).equalsIgnoreCase("")) {
return subs.stream().map(SubCommand::getName).map(String::toLowerCase).collect(Collectors.toList());
return subs.stream()
.map(m -> m.getName().toLowerCase())
.collect(Collectors.toList());
}
return subs.stream().map(SubCommand::getName).map(String::toLowerCase)
.filter(s -> s.toLowerCase().startsWith(args.get(0).toLowerCase())).collect(Collectors.toList());
return subs.stream()
.map(m -> m.getName().toLowerCase())
.filter(s -> s.toLowerCase().startsWith(args.get(0).toLowerCase()))
.collect(Collectors.toList());
}
Optional<SubCommand<Log>> o = subs.stream().filter(s -> s.getName().equalsIgnoreCase(args.get(0))).limit(1).findAny();
Optional<SubCommand<Log>> o = subs.stream()
.filter(s -> s.getName().equalsIgnoreCase(args.get(0)))
.limit(1)
.findAny();
if (!o.isPresent()) {
return Collections.emptyList();
}
@@ -23,13 +23,20 @@
package me.lucko.luckperms.commands.log.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.api.LogEntry;
import me.lucko.luckperms.commands.CommandResult;
import me.lucko.luckperms.commands.Predicate;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.Log;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
public class LogExport extends SubCommand<Log> {
@@ -39,7 +46,83 @@ public class LogExport extends SubCommand<Log> {
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Log log, List<String> args, String label) {
// TODO: implement this
return CommandResult.SUCCESS;
File f = new File(plugin.getMainDir(), args.get(0));
if (f.exists()) {
Message.LOG_EXPORT_ALREADY_EXISTS.send(sender, f.getAbsolutePath());
return CommandResult.INVALID_ARGS;
}
if (log.getContent().isEmpty()) {
Message.LOG_EXPORT_EMPTY.send(sender);
return CommandResult.STATE_ERROR;
}
try {
f.createNewFile();
} catch (IOException e) {
Message.LOG_EXPORT_FAILURE.send(sender);
e.printStackTrace();
return CommandResult.FAILURE;
}
if (!Files.isWritable(f.toPath())) {
Message.LOG_EXPORT_NOT_WRITABLE.send(sender, f.getAbsolutePath());
return CommandResult.FAILURE;
}
List<String> data = new ArrayList<>();
StringBuilder b = new StringBuilder();
for (LogEntry e : log.getContent()) {
b.setLength(0);
b.append("/luckperms ");
if (e.getType() == 'U') {
b.append("user ").append(e.getActed().toString()).append(" ").append(e.getAction());
}
group:
if (e.getType() == 'G') {
if (e.getAction().equalsIgnoreCase("create")) {
b.append("creategroup ").append(e.getActedName());
break group;
}
if (e.getAction().equalsIgnoreCase("delete")) {
b.append("deletegroup ").append(e.getActedName());
break group;
}
b.append("group ").append(e.getActedName()).append(" ").append(e.getAction());
}
track:
if (e.getType() == 'T') {
if (e.getAction().equalsIgnoreCase("create")) {
b.append("createtrack ").append(e.getActedName());
break track;
}
if (e.getAction().equalsIgnoreCase("delete")) {
b.append("deletetrack ").append(e.getActedName());
break track;
}
b.append("track ").append(e.getActedName()).append(" ").append(e.getAction());;
}
data.add(b.toString());
}
try {
Files.write(f.toPath(), data, Charset.defaultCharset());
Message.LOG_EXPORT_SUCCESS.send(sender, f.getAbsolutePath());
return CommandResult.SUCCESS;
} catch (IOException e) {
e.printStackTrace();
Message.LOG_EXPORT_FAILURE.send(sender);
return CommandResult.FAILURE;
}
}
}
@@ -45,11 +45,11 @@ public class LogUserHistory extends SubCommand<Log> {
@Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Log log, List<String> args, String label) {
String user = args.get(0);
final int[] page = {-999};
int page = -999;
if (args.size() == 2) {
try {
page[0] = Integer.parseInt(args.get(1));
page = Integer.parseInt(args.get(1));
} catch (NumberFormatException e) {
// invalid page
return showLog(-1, null, null, null);
@@ -58,11 +58,11 @@ public class LogUserHistory extends SubCommand<Log> {
UUID uuid = Util.parseUuid(user);
if (uuid != null) {
if (page[0] == -999) {
page[0] = log.getUserHistoryMaxPages(uuid);
if (page == -999) {
page = log.getUserHistoryMaxPages(uuid);
}
return showLog(page[0], uuid, sender, log);
return showLog(page, uuid, sender, log);
}
@@ -81,11 +81,11 @@ public class LogUserHistory extends SubCommand<Log> {
return CommandResult.INVALID_ARGS;
}
if (page[0] == -999) {
page[0] = log.getUserHistoryMaxPages(uuid1);
if (page == -999) {
page = log.getUserHistoryMaxPages(uuid1);
}
return showLog(page[0], uuid1, sender, log);
return showLog(page, uuid1, sender, log);
}
Message.USER_INVALID_ENTRY.send(sender, user);
@@ -0,0 +1,83 @@
/*
* 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.commands.misc;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.CommandResult;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SingleMainCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.Importer;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.util.List;
public class ImportCommand extends SingleMainCommand {
public ImportCommand() {
super("Import", "/%s import <file>", 1, Permission.IMPORT);
}
@Override
protected CommandResult execute(LuckPermsPlugin plugin, Sender sender, List<String> args, String label) {
if (args.size() == 0) {
sendUsage(sender, label);
return CommandResult.INVALID_ARGS;
}
Importer importer = plugin.getImporter();
File f = new File(plugin.getMainDir(), args.get(0));
if (!f.exists()) {
Message.IMPORT_LOG_DOESNT_EXIST.send(sender, f.getAbsolutePath());
return CommandResult.INVALID_ARGS;
}
if (!Files.isReadable(f.toPath())) {
Message.IMPORT_LOG_NOT_READABLE.send(sender, f.getAbsolutePath());
return CommandResult.FAILURE;
}
List<String> commands;
try {
commands = Files.readAllLines(f.toPath(), Charset.defaultCharset());
} catch (IOException e) {
e.printStackTrace();
Message.IMPORT_LOG_FAILURE.send(sender);
return CommandResult.FAILURE;
}
if (!importer.startRun()) {
Message.IMPORT_ALREADY_RUNNING.send(sender);
return CommandResult.STATE_ERROR;
}
// Run the importer in its own thread.
plugin.doAsync(() -> importer.start(sender, commands));
return CommandResult.SUCCESS;
}
}
@@ -28,7 +28,7 @@ import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SingleMainCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntryBuilder;
import me.lucko.luckperms.data.LogEntry;
import me.lucko.luckperms.utils.ArgumentChecker;
import java.util.List;
@@ -62,7 +62,7 @@ public class CreateTrack extends SingleMainCommand {
}
Message.CREATE_SUCCESS.send(sender, trackName);
LogEntryBuilder.get().actor(sender).actedName(trackName).type('T').action("create").submit(plugin);
LogEntry.build().actor(sender).actedName(trackName).type('T').action("create").build().submit(plugin);
plugin.runUpdateTask();
return CommandResult.SUCCESS;
}
@@ -28,7 +28,7 @@ import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SingleMainCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntryBuilder;
import me.lucko.luckperms.data.LogEntry;
import me.lucko.luckperms.tracks.Track;
import me.lucko.luckperms.utils.ArgumentChecker;
@@ -72,7 +72,7 @@ public class DeleteTrack extends SingleMainCommand {
}
Message.DELETE_SUCCESS.send(sender, trackName);
LogEntryBuilder.get().actor(sender).actedName(trackName).type('T').action("delete").submit(plugin);
LogEntry.build().actor(sender).actedName(trackName).type('T').action("delete").build().submit(plugin);
plugin.runUpdateTask();
return CommandResult.SUCCESS;
}
@@ -86,7 +86,9 @@ public class DeleteTrack extends SingleMainCommand {
return tracks;
}
return tracks.stream().filter(s -> s.toLowerCase().startsWith(args.get(0).toLowerCase())).collect(Collectors.toList());
return tracks.stream()
.filter(s -> s.toLowerCase().startsWith(args.get(0).toLowerCase()))
.collect(Collectors.toList());
}
return Collections.emptyList();
@@ -26,7 +26,7 @@ import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.*;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntryBuilder;
import me.lucko.luckperms.data.LogEntry;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.tracks.Track;
@@ -64,9 +64,9 @@ public class TrackAppend extends SubCommand<Track> {
track.appendGroup(group);
Message.TRACK_APPEND_SUCCESS.send(sender, group.getName(), track.getName());
Message.EMPTY.send(sender, Util.listToArrowSep(track.getGroups(), group.getName()));
LogEntryBuilder.get().actor(sender).acted(track)
LogEntry.build().actor(sender).acted(track)
.action("append " + group.getName())
.submit(plugin);
.build().submit(plugin);
save(track, sender, plugin);
return CommandResult.SUCCESS;
} catch (ObjectAlreadyHasException e) {
@@ -29,7 +29,7 @@ import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntryBuilder;
import me.lucko.luckperms.data.LogEntry;
import me.lucko.luckperms.tracks.Track;
import java.util.List;
@@ -44,7 +44,7 @@ public class TrackClear extends SubCommand<Track> {
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Track track, List<String> args, String label) {
track.clearGroups();
Message.TRACK_CLEAR.send(sender, track.getName());
LogEntryBuilder.get().actor(sender).acted(track).action("clear").submit(plugin);
LogEntry.build().actor(sender).acted(track).action("clear").build().submit(plugin);
save(track, sender, plugin);
return CommandResult.SUCCESS;
}
@@ -26,7 +26,7 @@ import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.*;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntryBuilder;
import me.lucko.luckperms.data.LogEntry;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.tracks.Track;
@@ -72,9 +72,9 @@ public class TrackInsert extends SubCommand<Track> {
track.insertGroup(group, pos - 1);
Message.TRACK_INSERT_SUCCESS.send(sender, group.getName(), track.getName(), pos);
Message.EMPTY.send(sender, Util.listToArrowSep(track.getGroups(), group.getName()));
LogEntryBuilder.get().actor(sender).acted(track)
LogEntry.build().actor(sender).acted(track)
.action("insert " + group.getName() + " " + pos)
.submit(plugin);
.build().submit(plugin);
save(track, sender, plugin);
return CommandResult.SUCCESS;
} catch (ObjectAlreadyHasException e) {
@@ -26,7 +26,7 @@ import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.commands.*;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntryBuilder;
import me.lucko.luckperms.data.LogEntry;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import me.lucko.luckperms.tracks.Track;
import me.lucko.luckperms.utils.ArgumentChecker;
@@ -52,9 +52,9 @@ public class TrackRemove extends SubCommand<Track> {
track.removeGroup(groupName);
Message.TRACK_REMOVE_SUCCESS.send(sender, groupName, track.getName());
Message.EMPTY.send(sender, Util.listToArrowSep(track.getGroups()));
LogEntryBuilder.get().actor(sender).acted(track)
LogEntry.build().actor(sender).acted(track)
.action("remove " + groupName)
.submit(plugin);
.build().submit(plugin);
save(track, sender, plugin);
return CommandResult.SUCCESS;
} catch (ObjectLacksException e) {
@@ -29,7 +29,7 @@ import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntryBuilder;
import me.lucko.luckperms.data.LogEntry;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.users.User;
@@ -74,24 +74,24 @@ public class UserAddGroup extends SubCommand<User> {
if (args.size() == 2) {
user.addGroup(group, server);
Message.USER_ADDGROUP_SERVER_SUCCESS.send(sender, user.getName(), groupName, server);
LogEntryBuilder.get().actor(sender).acted(user)
LogEntry.build().actor(sender).acted(user)
.action("addgroup " + group.getName() + " " + server)
.submit(plugin);
.build().submit(plugin);
} else {
final String world = args.get(2).toLowerCase();
user.addGroup(group, server, world);
Message.USER_ADDGROUP_SERVER_WORLD_SUCCESS.send(sender, user.getName(), groupName, server, world);
LogEntryBuilder.get().actor(sender).acted(user)
LogEntry.build().actor(sender).acted(user)
.action("addgroup " + group.getName() + " " + server + " " + world)
.submit(plugin);
.build().submit(plugin);
}
} else {
user.addGroup(group);
Message.USER_ADDGROUP_SUCCESS.send(sender, user.getName(), groupName);
LogEntryBuilder.get().actor(sender).acted(user)
LogEntry.build().actor(sender).acted(user)
.action("addgroup " + group.getName())
.submit(plugin);
.build().submit(plugin);
}
save(user, sender, plugin);
@@ -29,7 +29,7 @@ import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntryBuilder;
import me.lucko.luckperms.data.LogEntry;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.users.User;
@@ -56,10 +56,14 @@ public class UserAddTempGroup extends SubCommand<User> {
long duration;
try {
duration = DateUtil.parseDateDiff(args.get(1), true);
} catch (DateUtil.IllegalDateException e) {
Message.ILLEGAL_DATE_ERROR.send(sender, args.get(1));
return CommandResult.INVALID_ARGS;
duration = Long.parseLong(args.get(1));
} catch (NumberFormatException e) {
try {
duration = DateUtil.parseDateDiff(args.get(1), true);
} catch (DateUtil.IllegalDateException e1) {
Message.ILLEGAL_DATE_ERROR.send(sender, args.get(1));
return CommandResult.INVALID_ARGS;
}
}
if (DateUtil.shouldExpire(duration)) {
@@ -90,25 +94,25 @@ public class UserAddTempGroup extends SubCommand<User> {
user.addGroup(group, server, duration);
Message.USER_ADDTEMPGROUP_SERVER_SUCCESS.send(sender, user.getName(), groupName, server,
DateUtil.formatDateDiff(duration));
LogEntryBuilder.get().actor(sender).acted(user)
LogEntry.build().actor(sender).acted(user)
.action("addtempgroup " + group.getName() + " " + duration + " " + server)
.submit(plugin);
.build().submit(plugin);
} else {
final String world = args.get(3).toLowerCase();
user.addGroup(group, server, world, duration);
Message.USER_ADDTEMPGROUP_SERVER_WORLD_SUCCESS.send(sender, user.getName(), groupName, server,
world, DateUtil.formatDateDiff(duration));
LogEntryBuilder.get().actor(sender).acted(user)
LogEntry.build().actor(sender).acted(user)
.action("addtempgroup " + group.getName() + " " + duration + " " + server + " " + world)
.submit(plugin);
.build().submit(plugin);
}
} else {
user.addGroup(group, duration);
Message.USER_ADDTEMPGROUP_SUCCESS.send(sender, user.getName(), groupName, DateUtil.formatDateDiff(duration));
LogEntryBuilder.get().actor(sender).acted(user)
LogEntry.build().actor(sender).acted(user)
.action("addtempgroup " + group.getName() + " " + duration)
.submit(plugin);
.build().submit(plugin);
}
save(user, sender, plugin);
@@ -29,7 +29,7 @@ import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntryBuilder;
import me.lucko.luckperms.data.LogEntry;
import me.lucko.luckperms.users.User;
import java.util.List;
@@ -45,7 +45,7 @@ public class UserClear extends SubCommand<User> {
user.clearNodes();
plugin.getUserManager().giveDefaults(user);
Message.CLEAR_SUCCESS.send(sender, user.getName());
LogEntryBuilder.get().actor(sender).acted(user).action("clear").submit(plugin);
LogEntry.build().actor(sender).acted(user).action("clear").build().submit(plugin);
save(user, sender, plugin);
return CommandResult.SUCCESS;
@@ -23,10 +23,13 @@
package me.lucko.luckperms.commands.user.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.api.event.events.UserDemoteEvent;
import me.lucko.luckperms.api.implementation.internal.TrackLink;
import me.lucko.luckperms.api.implementation.internal.UserLink;
import me.lucko.luckperms.commands.*;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntryBuilder;
import me.lucko.luckperms.data.LogEntry;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import me.lucko.luckperms.groups.Group;
@@ -103,10 +106,11 @@ public class UserDemote extends SubCommand<User> {
Message.USER_DEMOTE_SUCCESS_PROMOTE.send(sender, track.getName(), old, previousGroup.getName());
Message.USER_DEMOTE_SUCCESS_REMOVE.send(sender, user.getName(), old, previousGroup.getName(), previousGroup.getName());
Message.EMPTY.send(sender, Util.listToArrowSep(track.getGroups(), previousGroup.getName(), old, true));
LogEntryBuilder.get().actor(sender).acted(user)
LogEntry.build().actor(sender).acted(user)
.action("demote " + track.getName() + "(from " + old + " to " + previousGroup.getName() + ")")
.submit(plugin);
.build().submit(plugin);
save(user, sender, plugin);
plugin.getApiProvider().fireEventAsync(new UserDemoteEvent(new TrackLink(track), new UserLink(user), old, previousGroup.getName()));
return CommandResult.SUCCESS;
}
@@ -23,10 +23,13 @@
package me.lucko.luckperms.commands.user.subcommands;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.api.event.events.UserPromoteEvent;
import me.lucko.luckperms.api.implementation.internal.TrackLink;
import me.lucko.luckperms.api.implementation.internal.UserLink;
import me.lucko.luckperms.commands.*;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntryBuilder;
import me.lucko.luckperms.data.LogEntry;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import me.lucko.luckperms.groups.Group;
@@ -103,10 +106,11 @@ public class UserPromote extends SubCommand<User> {
Message.USER_PROMOTE_SUCCESS_PROMOTE.send(sender, track.getName(), old, nextGroup.getName());
Message.USER_PROMOTE_SUCCESS_REMOVE.send(sender, user.getName(), old, nextGroup.getName(), nextGroup.getName());
Message.EMPTY.send(sender, Util.listToArrowSep(track.getGroups(), old, nextGroup.getName(), false));
LogEntryBuilder.get().actor(sender).acted(user)
LogEntry.build().actor(sender).acted(user)
.action("promote " + track.getName() + "(from " + old + " to " + nextGroup.getName() + ")")
.submit(plugin);
.build().submit(plugin);
save(user, sender, plugin);
plugin.getApiProvider().fireEventAsync(new UserPromoteEvent(new TrackLink(track), new UserLink(user), old, nextGroup.getName()));
return CommandResult.SUCCESS;
}
@@ -29,7 +29,7 @@ import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntryBuilder;
import me.lucko.luckperms.data.LogEntry;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import me.lucko.luckperms.users.User;
import me.lucko.luckperms.utils.ArgumentChecker;
@@ -68,24 +68,24 @@ public class UserRemoveGroup extends SubCommand<User> {
if (args.size() == 2) {
user.unsetPermission("group." + groupName, server);
Message.USER_REMOVEGROUP_SERVER_SUCCESS.send(sender, user.getName(), groupName, server);
LogEntryBuilder.get().actor(sender).acted(user)
LogEntry.build().actor(sender).acted(user)
.action("removegroup " + groupName + " " + server)
.submit(plugin);
.build().submit(plugin);
} else {
final String world = args.get(2).toLowerCase();
user.unsetPermission("group." + groupName, server, world);
Message.USER_REMOVEGROUP_SERVER_WORLD_SUCCESS.send(sender, user.getName(), groupName, server, world);
LogEntryBuilder.get().actor(sender).acted(user)
LogEntry.build().actor(sender).acted(user)
.action("removegroup " + groupName + " " + server + " " + world)
.submit(plugin);
.build().submit(plugin);
}
} else {
user.unsetPermission("group." + groupName);
Message.USER_REMOVEGROUP_SUCCESS.send(sender, user.getName(), groupName);
LogEntryBuilder.get().actor(sender).acted(user)
LogEntry.build().actor(sender).acted(user)
.action("removegroup " + groupName)
.submit(plugin);
.build().submit(plugin);
}
save(user, sender, plugin);
@@ -29,7 +29,7 @@ import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntryBuilder;
import me.lucko.luckperms.data.LogEntry;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import me.lucko.luckperms.users.User;
import me.lucko.luckperms.utils.ArgumentChecker;
@@ -63,24 +63,24 @@ public class UserRemoveTempGroup extends SubCommand<User> {
if (args.size() == 2) {
user.unsetPermission("group." + groupName, server, true);
Message.USER_REMOVETEMPGROUP_SERVER_SUCCESS.send(sender, user.getName(), groupName, server);
LogEntryBuilder.get().actor(sender).acted(user)
LogEntry.build().actor(sender).acted(user)
.action("removetempgroup " + groupName + " " + server)
.submit(plugin);
.build().submit(plugin);
} else {
final String world = args.get(2).toLowerCase();
user.unsetPermission("group." + groupName, server, world, true);
Message.USER_REMOVETEMPGROUP_SERVER_WORLD_SUCCESS.send(sender, user.getName(), groupName, server, world);
LogEntryBuilder.get().actor(sender).acted(user)
LogEntry.build().actor(sender).acted(user)
.action("removetempgroup " + groupName + " " + server + " " + world)
.submit(plugin);
.build().submit(plugin);
}
} else {
user.unsetPermission("group." + groupName, true);
Message.USER_REMOVETEMPGROUP_SUCCESS.send(sender, user.getName(), groupName);
LogEntryBuilder.get().actor(sender).acted(user)
LogEntry.build().actor(sender).acted(user)
.action("removetempgroup " + groupName)
.submit(plugin);
.build().submit(plugin);
}
save(user, sender, plugin);
@@ -30,7 +30,7 @@ import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Patterns;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntryBuilder;
import me.lucko.luckperms.data.LogEntry;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.users.User;
import me.lucko.luckperms.utils.ArgumentChecker;
@@ -77,24 +77,24 @@ public class UserSetPermission extends SubCommand<User> {
if (args.size() == 3) {
user.setPermission(node, b, server);
Message.SETPERMISSION_SERVER_SUCCESS.send(sender, node, bool, user.getName(), server);
LogEntryBuilder.get().actor(sender).acted(user)
LogEntry.build().actor(sender).acted(user)
.action("set " + node + " " + b + " " + server)
.submit(plugin);
.build().submit(plugin);
} else {
final String world = args.get(3).toLowerCase();
user.setPermission(node, b, server, world);
Message.SETPERMISSION_SERVER_WORLD_SUCCESS.send(sender, node, bool, user.getName(), server, world);
LogEntryBuilder.get().actor(sender).acted(user)
LogEntry.build().actor(sender).acted(user)
.action("set " + node + " " + b + " " + server + " " + world)
.submit(plugin);
.build().submit(plugin);
}
} else {
user.setPermission(node, b);
Message.SETPERMISSION_SUCCESS.send(sender, node, bool, user.getName());
LogEntryBuilder.get().actor(sender).acted(user)
LogEntry.build().actor(sender).acted(user)
.action("set " + node + " " + b)
.submit(plugin);
.build().submit(plugin);
}
save(user, sender, plugin);
@@ -29,7 +29,7 @@ import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntryBuilder;
import me.lucko.luckperms.data.LogEntry;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.users.User;
@@ -61,9 +61,9 @@ public class UserSetPrimaryGroup extends SubCommand<User> {
user.setPrimaryGroup(group.getName());
Message.USER_PRIMARYGROUP_SUCCESS.send(sender, user.getName(), group.getName());
LogEntryBuilder.get().actor(sender).acted(user)
LogEntry.build().actor(sender).acted(user)
.action("setprimarygroup " + group.getName())
.submit(plugin);
.build().submit(plugin);
save(user, sender, plugin);
return CommandResult.SUCCESS;
@@ -30,7 +30,7 @@ import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Patterns;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntryBuilder;
import me.lucko.luckperms.data.LogEntry;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.users.User;
import me.lucko.luckperms.utils.ArgumentChecker;
@@ -69,10 +69,14 @@ public class UserSetTempPermission extends SubCommand<User> {
long duration;
try {
duration = DateUtil.parseDateDiff(args.get(2), true);
} catch (DateUtil.IllegalDateException e) {
Message.ILLEGAL_DATE_ERROR.send(sender, args.get(2));
return CommandResult.INVALID_ARGS;
duration = Long.parseLong(args.get(2));
} catch (NumberFormatException e) {
try {
duration = DateUtil.parseDateDiff(args.get(2), true);
} catch (DateUtil.IllegalDateException e1) {
Message.ILLEGAL_DATE_ERROR.send(sender, args.get(2));
return CommandResult.INVALID_ARGS;
}
}
if (DateUtil.shouldExpire(duration)) {
@@ -91,24 +95,24 @@ public class UserSetTempPermission extends SubCommand<User> {
if (args.size() == 4) {
user.setPermission(node, b, server, duration);
Message.SETPERMISSION_TEMP_SERVER_SUCCESS.send(sender, node, bool, user.getName(), server, DateUtil.formatDateDiff(duration));
LogEntryBuilder.get().actor(sender).acted(user)
LogEntry.build().actor(sender).acted(user)
.action("settemp " + node + " " + b + " " + duration + " " + server)
.submit(plugin);
.build().submit(plugin);
} else {
final String world = args.get(4).toLowerCase();
user.setPermission(node, b, server, world, duration);
Message.SETPERMISSION_TEMP_SERVER_WORLD_SUCCESS.send(sender, node, bool, user.getName(), server, world, DateUtil.formatDateDiff(duration));
LogEntryBuilder.get().actor(sender).acted(user)
LogEntry.build().actor(sender).acted(user)
.action("settemp " + node + " " + b + " " + duration + " " + server + " " + world)
.submit(plugin);
.build().submit(plugin);
}
} else {
user.setPermission(node, b, duration);
Message.SETPERMISSION_TEMP_SUCCESS.send(sender, node, bool, user.getName(), DateUtil.formatDateDiff(duration));
LogEntryBuilder.get().actor(sender).acted(user)
LogEntry.build().actor(sender).acted(user)
.action("settemp " + node + " " + b + " " + duration)
.submit(plugin);
.build().submit(plugin);
}
save(user, sender, plugin);
@@ -30,7 +30,7 @@ import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Patterns;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntryBuilder;
import me.lucko.luckperms.data.LogEntry;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import me.lucko.luckperms.users.User;
import me.lucko.luckperms.utils.ArgumentChecker;
@@ -68,24 +68,24 @@ public class UserUnSetPermission extends SubCommand<User> {
if (args.size() == 2) {
user.unsetPermission(node, server);
Message.UNSETPERMISSION_SERVER_SUCCESS.send(sender, node, user.getName(), server);
LogEntryBuilder.get().actor(sender).acted(user)
LogEntry.build().actor(sender).acted(user)
.action("unset " + node + " " + server)
.submit(plugin);
.build().submit(plugin);
} else {
final String world = args.get(2).toLowerCase();
user.unsetPermission(node, server, world);
Message.UNSETPERMISSION_SERVER_WORLD_SUCCESS.send(sender, node, user.getName(), server, world);
LogEntryBuilder.get().actor(sender).acted(user)
LogEntry.build().actor(sender).acted(user)
.action("unset " + node + " " + server + " " + world)
.submit(plugin);
.build().submit(plugin);
}
} else {
user.unsetPermission(node);
Message.UNSETPERMISSION_SUCCESS.send(sender, node, user.getName());
LogEntryBuilder.get().actor(sender).acted(user)
LogEntry.build().actor(sender).acted(user)
.action("unset " + node)
.submit(plugin);
.build().submit(plugin);
}
save(user, sender, plugin);
@@ -30,7 +30,7 @@ import me.lucko.luckperms.commands.SubCommand;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Patterns;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.data.LogEntryBuilder;
import me.lucko.luckperms.data.LogEntry;
import me.lucko.luckperms.exceptions.ObjectLacksException;
import me.lucko.luckperms.users.User;
import me.lucko.luckperms.utils.ArgumentChecker;
@@ -69,24 +69,24 @@ public class UserUnsetTempPermission extends SubCommand<User> {
if (args.size() == 2) {
user.unsetPermission(node, server, true);
Message.UNSET_TEMP_PERMISSION_SERVER_SUCCESS.send(sender, node, user.getName(), server);
LogEntryBuilder.get().actor(sender).acted(user)
LogEntry.build().actor(sender).acted(user)
.action("unsettemp " + node + " " + server)
.submit(plugin);
.build().submit(plugin);
} else {
final String world = args.get(2).toLowerCase();
user.unsetPermission(node, server, world, true);
Message.UNSET_TEMP_PERMISSION_SERVER_WORLD_SUCCESS.send(sender, node, user.getName(), server, world);
LogEntryBuilder.get().actor(sender).acted(user)
LogEntry.build().actor(sender).acted(user)
.action("unsettemp " + node + " " + server + " " + world)
.submit(plugin);
.build().submit(plugin);
}
} else {
user.unsetPermission(node, true);
Message.UNSET_TEMP_PERMISSION_SUCCESS.send(sender, node, user.getName());
LogEntryBuilder.get().actor(sender).acted(user)
LogEntry.build().actor(sender).acted(user)
.action("unsettemp " + node)
.submit(plugin);
.build().submit(plugin);
}
save(user, sender, plugin);
@@ -26,6 +26,8 @@ import lombok.AllArgsConstructor;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.commands.Util;
import java.util.IllegalFormatException;
@SuppressWarnings("SpellCheckingInspection")
@AllArgsConstructor
public enum Message {
@@ -119,25 +121,24 @@ public enum Message {
UPDATE_TASK_RUN("&bRunning update task for all online users.", true),
INFO(
PREFIX + "&6Running &bLuckPerms v%s&6." + "\n" +
PREFIX + "&eAuthor: &6Luck" + "\n" +
PREFIX + "&eStorage Method: &6%s" + "\n" +
PREFIX + "&eServer Name: &6%s" + "\n" +
PREFIX + "&eDefault Group: &6%s" + "\n" +
PREFIX + "&eSync Interval: &6%s minutes" + "\n" +
PREFIX + "&eInclude Global Perms: &6%s" + "\n" +
PREFIX + "&eOnline Mode: &6%s" + "\n" +
PREFIX + "&eApply Wildcards: &6%s" + "\n" +
PREFIX + "&eApply Regex: &6%s" + "\n" +
PREFIX + "&eApply Shorthand: &6%s",
PREFIX + "&6Running &bLuckPerms v%s&6 by &bLuck&6." + "\n" +
PREFIX + "&f-> &eStorage Method: &6%s" + "\n" +
PREFIX + "&f-> &eServer Name: &6%s" + "\n" +
PREFIX + "&f-> &eDefault Group: &6%s" + "\n" +
PREFIX + "&f-> &eSync Interval: &6%s minutes" + "\n" +
PREFIX + "&f-> &eInclude Global Perms: &6%s" + "\n" +
PREFIX + "&f-> &eOnline Mode: &6%s" + "\n" +
PREFIX + "&f-> &eApply Wildcards: &6%s" + "\n" +
PREFIX + "&f-> &eApply Regex: &6%s" + "\n" +
PREFIX + "&f-> &eApply Shorthand: &6%s",
false
),
DEBUG(
PREFIX + "&d&l> &dDebug Info" + "\n" +
PREFIX + "&eOnline Players: &6%s" + "\n" +
PREFIX + "&eLoaded Users: &6%s" + "\n" +
PREFIX + "&eLoaded Groups: &6%s" + "\n" +
PREFIX + "&eLoaded Tracks: &6%s",
PREFIX + "&f> &eOnline Players: &6%s" + "\n" +
PREFIX + "&f> &eLoaded Users: &6%s" + "\n" +
PREFIX + "&f> &eLoaded Groups: &6%s" + "\n" +
PREFIX + "&f> &eLoaded Tracks: &6%s",
false
),
@@ -159,11 +160,11 @@ public enum Message {
SETPERMISSION_TEMP_SERVER_SUCCESS("&aSet &b%s&a to &b%s&a for &b%s&a on server &b%s&a for a duration of &b%s&a.", true),
SETPERMISSION_TEMP_SERVER_WORLD_SUCCESS("&aSet &b%s&a to &b%s&a for &b%s&a on server &b%s&a, world &b%s&a, for a duration of &b%s&a.", true),
UNSETPERMISSION_SUCCESS("&aUnset &b%s&a for &b%s&a.", true),
UNSETPERMISSION_SERVER_SUCCESS("&aUnset &b%s&a for &b%s&a on server &b%$s&a.", true),
UNSETPERMISSION_SERVER_WORLD_SUCCESS("&aUnset &b%s&a for &b%s&a on server &b%$s&a, world &b%$s&a.", true),
UNSETPERMISSION_SERVER_SUCCESS("&aUnset &b%s&a for &b%s&a on server &b%s&a.", true),
UNSETPERMISSION_SERVER_WORLD_SUCCESS("&aUnset &b%s&a for &b%s&a on server &b%s&a, world &b%s&a.", true),
UNSET_TEMP_PERMISSION_SUCCESS("&aUnset temporary permission &b%s&a for &b%s&a.", true),
UNSET_TEMP_PERMISSION_SERVER_SUCCESS("&aUnset temporary permission &b%s&a for &b%s&a on server &b%$s&a.", true),
UNSET_TEMP_PERMISSION_SERVER_WORLD_SUCCESS("&aUnset temporary permission &b%s&a for &b%s&a on server &b%$s&a, world &b%$s&a.", true),
UNSET_TEMP_PERMISSION_SERVER_SUCCESS("&aUnset temporary permission &b%s&a for &b%s&a on server &b%s&a.", true),
UNSET_TEMP_PERMISSION_SERVER_WORLD_SUCCESS("&aUnset temporary permission &b%s&a for &b%s&a on server &b%s&a, world &b%s&a.", true),
CLEAR_SUCCESS("&b%s&a's permissions were cleared.", true),
ILLEGAL_DATE_ERROR("Could not parse date '%s'.", true),
PAST_DATE_ERROR("You cannot set a date in the past!", true),
@@ -270,22 +271,34 @@ public enum Message {
LOG_HISTORY_GROUP_HEADER("&aShowing history for group &b%s &a(page &f%s&a of &f%s&a)", true),
LOG_HISTORY_TRACK_HEADER("&aShowing history for track &b%s &a(page &f%s&a of &f%s&a)", true),
IMPORT_PROGRESS("&e(Import) &d-> &6%s% complete &7- &e%s&6/&e%s &6operations complete with &c%s &6errors.", true),
IMPORT_PROGRESS_SIN("&e(Import) &d-> &6%s% complete &7- &e%s&6/&e%s &6operations complete with &c%s &6error.", true),
LOG_EXPORT_ALREADY_EXISTS("Error: File %s already exists.", true),
LOG_EXPORT_NOT_WRITABLE("Error: File %s is not writable.", true),
LOG_EXPORT_EMPTY("The log is empty and therefore cannot be exported.", true),
LOG_EXPORT_FAILURE("An unexpected error occured whilst writing to the file.", true),
LOG_EXPORT_SUCCESS("&aSuccessfully exported the log to &b%s&a.", true),
IMPORT_ALREADY_RUNNING("Another import process is already running. Please wait for it to finish and try again.", true),
IMPORT_LOG_DOESNT_EXIST("Error: File %s does not exist.", true),
IMPORT_LOG_NOT_READABLE("Error: File %s is not readable.", true),
IMPORT_LOG_FAILURE("An unexpected error occured whilst reading from the log file.", true),
IMPORT_PROGRESS("&e(Import) &d-> &f%s &6percent complete &7- &e%s&6/&e%s &6operations complete with &c%s &6errors.", true),
IMPORT_PROGRESS_SIN("&e(Import) &d-> &f%s &6percent complete &7- &e%s&6/&e%s &6operations complete with &c%s &6error.", true),
IMPORT_START("&e(Import) &d-> &6Starting import process.", true),
IMPORT_END_COMPLETE("&e(Import) &a&lCOMPLETED &7- took &e%s &7seconds - &7No errors.", true),
IMPORT_END_COMPLETE_ERR("&e(Import) &a&lCOMPLETED &7- took &e%s &7seconds - &c%s errors.", true),
IMPORT_END_COMPLETE_ERR_SIN("&e(Import) &a&lCOMPLETED &7- took &e%s &7seconds - &c%s error.", true),
IMPORT_END_ERROR_HEADER(
PREFIX + "&e(Import) &7-----> &6Showing Error #&e%s &7<-----" + "\n" +
PREFIX + "&e(Import) &7------------> &6Showing Error #&e%s &7<------------" + "\n" +
PREFIX + "&e(Import) &6Whilst executing: &fCommand #%s" + "\n" +
PREFIX + "&e(Import) &6Output:s",
PREFIX + "&e(Import) &6Type: &f%s" + "\n" +
PREFIX + "&e(Import) &6Output:",
false
),
IMPORT_END_ERROR_CONTENT("&e(Import) &7-> &c%s", true),
IMPORT_END_ERROR_FOOTER("&e(Import) &7<---------------------------->", true);
IMPORT_END_ERROR_CONTENT("&e(Import) &d-> &c%s", true),
IMPORT_END_ERROR_FOOTER("&e(Import) &7<------------------------------------------>", true);
private String message;
private boolean showPrefix;
@@ -296,10 +309,15 @@ public enum Message {
}
public void send(Sender sender, Object... objects) {
if (showPrefix) {
sender.sendMessage(Util.color(PREFIX + String.format(message, objects)));
} else {
sender.sendMessage(Util.color(String.format(message, objects)));
try {
if (showPrefix) {
sender.sendMessage(Util.color(PREFIX + String.format(message, objects)));
} else {
sender.sendMessage(Util.color(String.format(message, objects)));
}
} catch (IllegalFormatException e) {
System.out.println("Could not format message: " + this);
e.printStackTrace();
}
}
}
@@ -32,6 +32,7 @@ public enum Permission {
SYNC("sync", null),
INFO("info", null),
DEBUG("debug", null),
IMPORT("import", null),
CREATE_GROUP("creategroup", null),
DELETE_GROUP("deletegroup", null),
@@ -26,7 +26,7 @@ import lombok.AccessLevel;
import lombok.Getter;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.constants.Patterns;
import me.lucko.luckperms.storage.MySQLConfiguration;
import me.lucko.luckperms.storage.DatastoreConfiguration;
public abstract class LPConfiguration<T extends LuckPermsPlugin> {
@@ -70,7 +70,7 @@ public abstract class LPConfiguration<T extends LuckPermsPlugin> {
}
public int getSyncTime() {
return getInt("sql.sync-minutes", 3);
return getInt("data.sync-minutes", 3);
}
public String getDefaultGroupNode() {
@@ -101,12 +101,12 @@ public abstract class LPConfiguration<T extends LuckPermsPlugin> {
return getBoolean("apply-shorthand", true);
}
public MySQLConfiguration getDatabaseValues() {
return new MySQLConfiguration(
getString("sql.address", null),
getString("sql.database", null),
getString("sql.username", null),
getString("sql.password", null)
public DatastoreConfiguration getDatabaseValues() {
return new DatastoreConfiguration(
getString("data.address", null),
getString("data.database", null),
getString("data.username", null),
getString("data.password", null)
);
}
@@ -26,6 +26,11 @@ import lombok.AccessLevel;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.api.event.events.GroupRemoveEvent;
import me.lucko.luckperms.api.event.events.PermissionExpireEvent;
import me.lucko.luckperms.api.event.events.PermissionSetEvent;
import me.lucko.luckperms.api.event.events.PermissionUnsetEvent;
import me.lucko.luckperms.api.implementation.internal.PermissionHolderLink;
import me.lucko.luckperms.constants.Patterns;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
import me.lucko.luckperms.exceptions.ObjectLacksException;
@@ -252,11 +257,7 @@ public abstract class PermissionHolder {
* @throws ObjectAlreadyHasException if the object already has the permission
*/
public void setPermission(String node, boolean value) throws ObjectAlreadyHasException {
if (node.startsWith("global/")) node = node.replace("global/", "");
if (hasPermission(node, value)) {
throw new ObjectAlreadyHasException();
}
this.nodes.put(node, value);
setPermission(node, value, null, null, 0L);
}
/**
@@ -267,7 +268,7 @@ public abstract class PermissionHolder {
* @throws ObjectAlreadyHasException if the object already has the permission
*/
public void setPermission(String node, boolean value, String server) throws ObjectAlreadyHasException {
setPermission(server + "/" + node, value);
setPermission(node, value, server, null, 0L);
}
/**
@@ -279,7 +280,7 @@ public abstract class PermissionHolder {
* @throws ObjectAlreadyHasException if the object already has the permission
*/
public void setPermission(String node, boolean value, String server, String world) throws ObjectAlreadyHasException {
setPermission(server + "-" + world + "/" + node, value);
setPermission(node, value, server, world, 0L);
}
/**
@@ -290,7 +291,7 @@ public abstract class PermissionHolder {
* @throws ObjectAlreadyHasException if the object already has the permission
*/
public void setPermission(String node, boolean value, long expireAt) throws ObjectAlreadyHasException {
setPermission(node + "$" + expireAt, value);
setPermission(node, value, null, null, expireAt);
}
/**
@@ -302,7 +303,7 @@ public abstract class PermissionHolder {
* @throws ObjectAlreadyHasException if the object already has the permission
*/
public void setPermission(String node, boolean value, String server, long expireAt) throws ObjectAlreadyHasException {
setPermission(node + "$" + expireAt, value, server);
setPermission(node, value, server, null, expireAt);
}
/**
@@ -315,7 +316,43 @@ public abstract class PermissionHolder {
* @throws ObjectAlreadyHasException if the object already has the permission
*/
public void setPermission(String node, boolean value, String server, String world, long expireAt) throws ObjectAlreadyHasException {
setPermission(node + "$" + expireAt, value, server, world);
if (node.startsWith("global/")) node = node.replace("global/", "");
if (server != null && server.equals("")) server = null;
if (world != null && world.equals("")) world = null;
StringBuilder builder = new StringBuilder();
if (server != null) {
builder.append(server);
if (world != null) {
builder.append("-").append(world);
}
builder.append("/");
} else {
if (world != null) {
builder.append("global-").append(world);
}
builder.append("/");
}
builder.append(node);
if (expireAt != 0L) {
builder.append("$").append(expireAt);
}
final String finalNode = builder.toString();
if (hasPermission(node, value)) {
throw new ObjectAlreadyHasException();
}
this.nodes.put(finalNode, value);
plugin.getApiProvider().fireEventAsync(new PermissionSetEvent(
new PermissionHolderLink(this), node, value, server, world, expireAt));
}
/**
@@ -325,25 +362,7 @@ public abstract class PermissionHolder {
* @throws ObjectLacksException if the node wasn't already set
*/
public void unsetPermission(String node, boolean temporary) throws ObjectLacksException {
if (node.startsWith("global/")) node = node.replace("global/", "");
final String fNode = node;
Optional<String> match = Optional.empty();
if (temporary) {
match = this.nodes.keySet().stream()
.filter(n -> n.contains("$")).filter(n -> Patterns.TEMP_DELIMITER.split(n)[0].equalsIgnoreCase(fNode))
.findFirst();
} else {
if (this.nodes.containsKey(fNode)) {
match = Optional.of(fNode);
}
}
if (match.isPresent()) {
this.nodes.remove(match.get());
} else {
throw new ObjectLacksException();
}
unsetPermission(node, null, null, temporary);
}
/**
@@ -352,7 +371,7 @@ public abstract class PermissionHolder {
* @throws ObjectLacksException if the node wasn't already set
*/
public void unsetPermission(String node) throws ObjectLacksException {
unsetPermission(node, node.contains("$"));
unsetPermission(node, null, null, false);
}
/**
@@ -362,7 +381,7 @@ public abstract class PermissionHolder {
* @throws ObjectLacksException if the node wasn't already set
*/
public void unsetPermission(String node, String server) throws ObjectLacksException {
unsetPermission(server + "/" + node);
unsetPermission(node, server, null, false);
}
/**
@@ -373,7 +392,7 @@ public abstract class PermissionHolder {
* @throws ObjectLacksException if the node wasn't already set
*/
public void unsetPermission(String node, String server, String world) throws ObjectLacksException {
unsetPermission(server + "-" + world + "/" + node);
unsetPermission(node, server, world, false);
}
/**
@@ -384,7 +403,7 @@ public abstract class PermissionHolder {
* @throws ObjectLacksException if the node wasn't already set
*/
public void unsetPermission(String node, String server, boolean temporary) throws ObjectLacksException {
unsetPermission(server + "/" + node, temporary);
unsetPermission(node, server, null, temporary);
}
/**
@@ -396,7 +415,55 @@ public abstract class PermissionHolder {
* @throws ObjectLacksException if the node wasn't already set
*/
public void unsetPermission(String node, String server, String world, boolean temporary) throws ObjectLacksException {
unsetPermission(server + "-" + world + "/" + node, temporary);
if (node.startsWith("global/")) node = node.replace("global/", "");
if (server != null && server.equals("")) server = null;
if (world != null && world.equals("")) world = null;
StringBuilder builder = new StringBuilder();
if (server != null) {
builder.append(server);
if (world != null) {
builder.append("-").append(world);
}
builder.append("/");
} else {
if (world != null) {
builder.append("global-").append(world);
}
builder.append("/");
}
builder.append(node);
final String finalNode = builder.toString();
Optional<String> match = Optional.empty();
if (temporary) {
match = this.nodes.keySet().stream()
.filter(n -> n.contains("$"))
.filter(n -> Patterns.TEMP_DELIMITER.split(n)[0].equalsIgnoreCase(finalNode))
.findFirst();
} else {
if (this.nodes.containsKey(finalNode)) {
match = Optional.of(finalNode);
}
}
if (match.isPresent()) {
this.nodes.remove(match.get());
plugin.getApiProvider().fireEventAsync(new PermissionUnsetEvent(
new PermissionHolderLink(this), node, server, world, temporary));
if (node.startsWith("group.")) {
plugin.getApiProvider().fireEventAsync(new GroupRemoveEvent(
new PermissionHolderLink(this), Patterns.DOT.split(node, 2)[1], server, world, temporary));
}
} else {
throw new ObjectLacksException();
}
}
/**
@@ -467,12 +534,19 @@ public abstract class PermissionHolder {
/**
* Removes temporary permissions that have expired
* @return true if permissions had expired and were removed
*/
public void auditTemporaryPermissions() {
this.nodes.keySet().stream()
public boolean auditTemporaryPermissions() {
List<String> toExpire = this.nodes.keySet().stream()
.filter(s -> s.contains("$"))
.filter(s -> DateUtil.shouldExpire(Long.parseLong(Patterns.TEMP_DELIMITER.split(s)[1])))
.forEach(s -> this.nodes.remove(s));
.collect(Collectors.toList());
toExpire.forEach(s -> {
plugin.getApiProvider().fireEventAsync(new PermissionExpireEvent(new PermissionHolderLink(this), s));
this.nodes.remove(s);
});
return !toExpire.isEmpty();
}
private Map<String, Boolean> convertTemporaryPerms() {
@@ -696,15 +770,28 @@ public abstract class PermissionHolder {
}
private boolean matches(String entry, String possibleRegex) {
if (!possibleRegex.toLowerCase().startsWith("r=") || !plugin.getConfiguration().getApplyRegex()) {
return entry.equalsIgnoreCase(possibleRegex);
if (possibleRegex.toLowerCase().startsWith("r=") && plugin.getConfiguration().getApplyRegex()) {
Pattern p = Patterns.compile(possibleRegex.substring(2));
if (p == null) {
return false;
}
return p.matcher(entry).matches();
}
Pattern p = Patterns.compile(possibleRegex.substring(2));
if (p == null) {
if (possibleRegex.startsWith("(") && possibleRegex.endsWith(")") && possibleRegex.contains("|")) {
final String bits = possibleRegex.substring(1, possibleRegex.length() - 1);
String[] parts = Patterns.VERTICAL_BAR.split(bits);
for (String s : parts) {
if (s.equalsIgnoreCase(entry)) {
return true;
}
}
return false;
}
return p.matcher(entry).matches();
return entry.equalsIgnoreCase(possibleRegex);
}
private Map<String, Boolean> applyRegex(Map<String, Boolean> input, List<String> possibleNodes) {
@@ -55,7 +55,11 @@ public class UuidCache {
public UUID getExternalUUID(UUID internal) {
if (onlineMode) return internal;
Optional<UUID> external = cache.entrySet().stream().filter(e -> e.getValue().equals(internal)).map(Map.Entry::getKey).findFirst();
Optional<UUID> external = cache.entrySet().stream()
.filter(e -> e.getValue().equals(internal))
.map(Map.Entry::getKey)
.findFirst();
return external.isPresent() ? external.get() : internal;
}
@@ -41,13 +41,10 @@ import java.util.stream.Collectors;
* Executes a list of commands sequentially in a single thread.
*/
@RequiredArgsConstructor
public class Importer { // TODO: implement this
@Getter
private boolean running = false;
public class Importer {
private final CommandManager commandManager;
private boolean running = false;
private Sender executor = null;
private List<String> commands = null;
private Map<Integer, Result> cmdResult = null;
@@ -55,16 +52,22 @@ public class Importer { // TODO: implement this
private long lastMsg = 0;
private int executing = -1;
public synchronized void start(Sender executor, List<String> commands) {
if (isRunning()) {
throw new IllegalStateException("Import already running.");
public synchronized boolean startRun() {
if (running) {
return false;
}
running = true;
return true;
}
public void start(Sender executor, List<String> commands) {
this.executor = executor;
this.commands = commands.stream()
.map(s -> s.startsWith("/") ? s.substring(1) : s)
.map(s -> s.startsWith("perms ") ? s.substring(5) : s)
.map(s -> s.startsWith("perms ") ? s.substring(6) : s)
.map(s -> s.startsWith("luckperms ") ? s.substring(10) : s)
.collect(Collectors.toList());
cmdResult = new HashMap<>();
@@ -127,7 +130,7 @@ public class Importer { // TODO: implement this
int errIndex = 1;
for (Map.Entry<Integer, Result> e : cmdResult.entrySet()) {
if (e.getValue().getResult() != null && !e.getValue().getResult().booleanValue()) {
Message.IMPORT_END_ERROR_HEADER.send(executor, errIndex, e.getKey());
Message.IMPORT_END_ERROR_HEADER.send(executor, errIndex, e.getKey(), e.getValue().getResult().toString());
for (String s : e.getValue().getOutput()) {
Message.IMPORT_END_ERROR_CONTENT.send(executor, s);
}
@@ -140,7 +143,7 @@ public class Importer { // TODO: implement this
}
private void sendProgress(int executing) {
int percent = (executing / commands.size()) * 100;
int percent = (executing * 100) / commands.size();
int errors = 0;
for (Map.Entry<Integer, Result> e : cmdResult.entrySet()) {
@@ -0,0 +1,129 @@
/*
* 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.data;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.api.event.events.LogNotifyEvent;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.core.PermissionHolder;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.tracks.Track;
import me.lucko.luckperms.users.User;
import java.util.List;
import java.util.stream.Collectors;
public class LogEntry extends me.lucko.luckperms.api.LogEntry {
public static LogEntryBuilder build() {
return new LogEntryBuilder();
}
private LogEntry() {
super();
}
public void submit(LuckPermsPlugin plugin) {
plugin.getDatastore().logAction(this);
LogNotifyEvent event = new LogNotifyEvent(this);
plugin.getApiProvider().fireEvent(event);
if (event.isCancelled()) return;
final String msg = super.getFormatted();
List<Sender> senders = plugin.getSenders().stream()
.filter(Permission.LOG_NOTIFY::isAuthorized)
.collect(Collectors.toList());
senders.add(plugin.getConsoleSender());
senders.stream()
.filter(s -> !plugin.getIgnoringLogs().contains(s.getUuid()))
.forEach(s -> Message.LOG.send(s, msg));
}
public static class LogEntryBuilder extends AbstractLogEntryBuilder<LogEntry, LogEntry.LogEntryBuilder> {
@Override
protected LogEntry createObj() {
return new LogEntry();
}
@Override
protected LogEntryBuilder getThis() {
return this;
}
public LogEntryBuilder actor(Sender actor) {
super.actorName(actor.getName());
super.actor(actor.getUuid());
return this;
}
public LogEntryBuilder type(String type) {
super.type(type.toCharArray()[0]);
return this;
}
public LogEntryBuilder type(Object object) {
if (object instanceof User) {
super.type('U');
} else if (object instanceof Group) {
super.type('G');
} else if (object instanceof Track) {
super.type('T');
} else {
throw new IllegalArgumentException();
}
return this;
}
public LogEntryBuilder acted(PermissionHolder acted) {
if (acted instanceof User) {
super.actedName(((User) acted).getName());
super.acted(((User) acted).getUuid());
super.type('U');
} else if (acted instanceof Group) {
super.actedName(((Group) acted).getName());
super.type('G');
}
return this;
}
public LogEntryBuilder acted(Track track) {
super.actedName(track.getName());
super.type('T');
return this;
}
@Override
public LogEntry build() {
if (getTimestamp() == 0L) {
super.timestamp(System.currentTimeMillis() / 1000L);
}
return super.build();
}
}
}
@@ -1,173 +0,0 @@
/*
* 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.data;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.api.LogEntry;
import me.lucko.luckperms.api.data.Callback;
import me.lucko.luckperms.commands.Sender;
import me.lucko.luckperms.constants.Message;
import me.lucko.luckperms.constants.Permission;
import me.lucko.luckperms.core.PermissionHolder;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.tracks.Track;
import me.lucko.luckperms.users.User;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
public class LogEntryBuilder {
private long timestamp = 0L;
private UUID actor = null;
private String actorName = null;
private char type = Character.MIN_VALUE;
private UUID acted = null;
private String actedName = null;
private String action = null;
public static LogEntryBuilder get() {
return new LogEntryBuilder();
}
public LogEntryBuilder timestamp(long timestamp) {
this.timestamp = timestamp;
return this;
}
public LogEntryBuilder actor(UUID actor) {
this.actor = actor;
return this;
}
public LogEntryBuilder actorName(String actorName) {
this.actorName = actorName;
return this;
}
public LogEntryBuilder actor(Sender actor) {
this.actorName = actor.getName();
this.actor = actor.getUuid();
return this;
}
public LogEntryBuilder type(char type) {
this.type = type;
return this;
}
public LogEntryBuilder type(String type) {
this.type = type.toCharArray()[0];
return this;
}
public LogEntryBuilder type(Object object) {
if (object instanceof User) {
this.type = 'U';
} else if (object instanceof Group) {
this.type = 'G';
} else if (object instanceof Track) {
this.type = 'T';
} else {
throw new IllegalArgumentException();
}
return this;
}
public LogEntryBuilder acted(UUID acted) {
this.acted = acted;
return this;
}
public LogEntryBuilder actedName(String actedName) {
this.actedName = actedName;
return this;
}
public LogEntryBuilder acted(PermissionHolder acted) {
if (acted instanceof User) {
this.actedName = ((User) acted).getName();
this.acted = ((User) acted).getUuid();
this.type = 'U';
} else if (acted instanceof Group) {
this.actedName = ((Group) acted).getName();
this.type = 'G';
}
return this;
}
public LogEntryBuilder acted(Track track) {
this.actedName = track.getName();
this.type = 'T';
return this;
}
public LogEntryBuilder action(String action) {
this.action = action;
return this;
}
private Set<String> getEmpty() {
Set<String> s = new HashSet<>();
if (actor == null) {
s.add("actor");
}
if (actorName == null) {
s.add("actorname");
}
if (type == Character.MIN_VALUE) {
s.add("type");
}
if (actedName == null) {
s.add("actedname");
}
if (action == null) {
s.add("action");
}
return s;
}
public void submit(LuckPermsPlugin plugin) {
final LogEntry entry = build();
plugin.getDatastore().logAction(entry, Callback.empty());
final String msg = entry.getFormatted();
plugin.getSenders().stream()
.filter(Permission.LOG_NOTIFY::isAuthorized)
.filter(s -> !plugin.getIgnoringLogs().contains(s.getUuid()))
.forEach(s -> Message.LOG.send(s, msg));
}
public LogEntry build() {
if (timestamp == 0L) {
timestamp = System.currentTimeMillis() / 1000;
}
if (!getEmpty().isEmpty()) {
throw new IllegalStateException("Missing values: " + getEmpty().toString());
}
return new LogEntry(timestamp, actor, actorName, type, acted, actedName, action);
}
}
@@ -26,6 +26,9 @@ import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.api.event.events.GroupAddEvent;
import me.lucko.luckperms.api.implementation.internal.GroupLink;
import me.lucko.luckperms.api.implementation.internal.PermissionHolderLink;
import me.lucko.luckperms.constants.Patterns;
import me.lucko.luckperms.core.PermissionHolder;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
@@ -51,6 +54,11 @@ public class Group extends PermissionHolder implements Identifiable<String> {
this.name = name;
}
@Override
public String getId() {
return name;
}
/**
* check to see if a group inherits a group
* @param group The group to check membership of
@@ -87,7 +95,12 @@ public class Group extends PermissionHolder implements Identifiable<String> {
* @throws ObjectAlreadyHasException if the group already inherits the group
*/
public void setInheritGroup(Group group) throws ObjectAlreadyHasException {
setInheritGroup(group, "global");
if (group.getName().equalsIgnoreCase(this.getName())) {
throw new ObjectAlreadyHasException();
}
setPermission("group." + group.getName(), true);
getPlugin().getApiProvider().fireEventAsync(new GroupAddEvent(new PermissionHolderLink(this), new GroupLink(group), null, null, 0L));
}
/**
@@ -106,6 +119,7 @@ public class Group extends PermissionHolder implements Identifiable<String> {
}
setPermission("group." + group.getName(), true, server);
getPlugin().getApiProvider().fireEventAsync(new GroupAddEvent(new PermissionHolderLink(this), new GroupLink(group), server, null, 0L));
}
/**
@@ -125,6 +139,7 @@ public class Group extends PermissionHolder implements Identifiable<String> {
}
setPermission("group." + group.getName(), true, server, world);
getPlugin().getApiProvider().fireEventAsync(new GroupAddEvent(new PermissionHolderLink(this), new GroupLink(group), server, world, 0L));
}
/**
@@ -139,6 +154,7 @@ public class Group extends PermissionHolder implements Identifiable<String> {
}
setPermission("group." + group.getName(), true, expireAt);
getPlugin().getApiProvider().fireEventAsync(new GroupAddEvent(new PermissionHolderLink(this), new GroupLink(group), null, null, expireAt));
}
/**
@@ -158,6 +174,7 @@ public class Group extends PermissionHolder implements Identifiable<String> {
}
setPermission("group." + group.getName(), true, server, expireAt);
getPlugin().getApiProvider().fireEventAsync(new GroupAddEvent(new PermissionHolderLink(this), new GroupLink(group), server, null, expireAt));
}
/**
@@ -178,6 +195,7 @@ public class Group extends PermissionHolder implements Identifiable<String> {
}
setPermission("group." + group.getName(), true, server, world, expireAt);
getPlugin().getApiProvider().fireEventAsync(new GroupAddEvent(new PermissionHolderLink(this), new GroupLink(group), server, world, expireAt));
}
/**
@@ -309,9 +327,4 @@ public class Group extends PermissionHolder implements Identifiable<String> {
.map(s -> Patterns.DOT.split(s, 2)[1])
.collect(Collectors.toList());
}
@Override
public String getId() {
return name;
}
}
@@ -0,0 +1,53 @@
/*
* 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.runnables;
import lombok.AllArgsConstructor;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.core.PermissionHolder;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.users.User;
@AllArgsConstructor
public class ExpireTemporaryTask implements Runnable {
private final LuckPermsPlugin plugin;
@Override
public void run() {
boolean changes = false;
for (Group group : plugin.getGroupManager().getAll().values()) {
if (group.auditTemporaryPermissions()) {
changes = true;
}
}
if (changes) {
plugin.runUpdateTask();
return;
}
plugin.getUserManager().getAll().values().stream()
.filter(PermissionHolder::auditTemporaryPermissions)
.forEach(User::refreshPermissions);
}
}
@@ -24,24 +24,35 @@ package me.lucko.luckperms.runnables;
import lombok.AllArgsConstructor;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.api.event.events.PostSyncEvent;
import me.lucko.luckperms.api.event.events.PreSyncEvent;
@AllArgsConstructor
public class UpdateTask implements Runnable {
private final LuckPermsPlugin plugin;
/**
* Called ASYNC
*/
@Override
public void run() {
// Reload all of the groups
PreSyncEvent event = new PreSyncEvent();
plugin.getApiProvider().fireEvent(event);
if (event.isCancelled()) return;
// Reload all groups
plugin.getDatastore().loadAllGroups();
String defaultGroup = plugin.getConfiguration().getDefaultGroupName();
if (!plugin.getGroupManager().isLoaded(defaultGroup)) {
plugin.getDatastore().createAndLoadGroup(defaultGroup);
}
// Reload all of the tracks
// Reload all tracks
plugin.getDatastore().loadAllTracks();
// Refresh all online users.
plugin.getUserManager().updateAllUsers();
plugin.getApiProvider().fireEvent(new PostSyncEvent());;
}
}
@@ -90,7 +90,7 @@ public abstract class Datastore {
/*
These methods will schedule the operation to run async. The callback will be ran when the task is complete.
Callbacks are ran on the main Bukkit server thread (if applicable)
Callbacks are ran on the main server thread (except on BungeeCord)
*/
public void logAction(LogEntry entry, Callback<Boolean> callback) {
doAsync(() -> {
@@ -27,7 +27,7 @@ import lombok.Getter;
@Getter
@AllArgsConstructor
public class MySQLConfiguration implements me.lucko.luckperms.api.data.MySQLConfiguration {
public class DatastoreConfiguration implements me.lucko.luckperms.api.data.DatastoreConfiguration {
private final String address;
private final String database;
@@ -0,0 +1,75 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.storage;
import com.google.common.collect.ImmutableSet;
import lombok.experimental.UtilityClass;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.storage.methods.*;
import java.io.File;
import java.util.Set;
@UtilityClass
public class StorageFactory {
private static final Set<String> TYPES = ImmutableSet.of("flatfile", "mongodb", "mysql", "sqlite", "h2");
public static Datastore getDatastore(LuckPermsPlugin plugin, String defaultMethod) {
Datastore datastore;
plugin.getLog().info("Detecting storage method...");
String storageMethod = plugin.getConfiguration().getStorageMethod().toLowerCase();
if (!TYPES.contains(storageMethod)) {
plugin.getLog().severe("Storage method '" + storageMethod + "' not recognised. Using the default instead.");
storageMethod = defaultMethod;
}
switch (storageMethod) {
case "mysql":
plugin.getLog().info("Using MySQL as storage method.");
datastore = new MySQLDatastore(plugin, plugin.getConfiguration().getDatabaseValues());
break;
case "sqlite":
plugin.getLog().info("Using SQLite as storage method.");
datastore = new SQLiteDatastore(plugin, new File(plugin.getDataFolder(), "luckperms.sqlite"));
break;
case "h2":
plugin.getLog().info("Using H2 as storage method.");
datastore = new H2Datastore(plugin, new File(plugin.getDataFolder(), "luckperms.db"));
break;
case "mongodb":
plugin.getLog().info("Using MongoDB as storage method.");
datastore = new MongoDBDatastore(plugin, plugin.getConfiguration().getDatabaseValues());
break;
default:
plugin.getLog().info("Using Flatfile (JSON) as storage method.");
datastore = new FlatfileDatastore(plugin, plugin.getDataFolder());
break;
}
plugin.getLog().info("Initialising datastore...");
datastore.init();
return datastore;
}
}
@@ -385,7 +385,9 @@ public class FlatfileDatastore extends Datastore {
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());
List<String> groups = Arrays.stream(fileNames)
.map(s -> s.substring(0, s.length() - 5))
.collect(Collectors.toList());
plugin.getGroupManager().unloadAll();
groups.forEach(this::loadGroup);
@@ -511,7 +513,9 @@ public class FlatfileDatastore extends Datastore {
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());
List<String> tracks = Arrays.stream(fileNames)
.map(s -> s.substring(0, s.length() - 5))
.collect(Collectors.toList());
plugin.getTrackManager().unloadAll();
tracks.forEach(this::loadTrack);
@@ -0,0 +1,120 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.storage.methods;
import lombok.Cleanup;
import me.lucko.luckperms.LuckPermsPlugin;
import java.io.File;
import java.sql.*;
public class H2Datastore extends SQLDatastore {
private static final String CREATETABLE_UUID = "CREATE TABLE IF NOT EXISTS `lp_uuid` (`name` VARCHAR(16) NOT NULL, `uuid` VARCHAR(36) NOT NULL, PRIMARY KEY (`name`)) DEFAULT CHARSET=utf8;";
private static final String CREATETABLE_USERS = "CREATE TABLE IF NOT EXISTS `lp_users` (`uuid` VARCHAR(36) NOT NULL, `name` VARCHAR(16) NOT NULL, `primary_group` VARCHAR(36) NOT NULL, `perms` TEXT NOT NULL, PRIMARY KEY (`uuid`)) DEFAULT CHARSET=utf8;";
private static final String CREATETABLE_GROUPS = "CREATE TABLE IF NOT EXISTS `lp_groups` (`name` VARCHAR(36) NOT NULL, `perms` TEXT NULL, PRIMARY KEY (`name`)) DEFAULT CHARSET=utf8;";
private static final String CREATETABLE_TRACKS = "CREATE TABLE IF NOT EXISTS `lp_tracks` (`name` VARCHAR(36) NOT NULL, `groups` TEXT NULL, PRIMARY KEY (`name`)) DEFAULT CHARSET=utf8;";
private static final String CREATETABLE_ACTION = "CREATE TABLE IF NOT EXISTS `lp_actions` (`id` INT AUTO_INCREMENT NOT NULL, `time` BIGINT NOT NULL, `actor_uuid` VARCHAR(36) NOT NULL, `actor_name` VARCHAR(16) NOT NULL, `type` CHAR(1) NOT NULL, `acted_uuid` VARCHAR(36) NOT NULL, `acted_name` VARCHAR(36) NOT NULL, `action` VARCHAR(256) NOT NULL, PRIMARY KEY (`id`)) DEFAULT CHARSET=utf8;";
private final File file;
private Connection connection = null;
public H2Datastore(LuckPermsPlugin plugin, File file) {
super(plugin, "H2");
this.file = file;
}
@Override
public void init() {
if (!setupTables(CREATETABLE_UUID, CREATETABLE_USERS, CREATETABLE_GROUPS, CREATETABLE_TRACKS, CREATETABLE_ACTION)) {
plugin.getLog().severe("Error occurred whilst initialising the database.");
shutdown();
} else {
setAcceptingLogins(true);
}
}
@Override
boolean runQuery(QueryPS queryPS) {
boolean success = false;
try {
Connection connection = getConnection();
if (connection == null || connection.isClosed()) {
throw new IllegalStateException("SQL connection is null");
}
@Cleanup PreparedStatement preparedStatement = connection.prepareStatement(queryPS.getQuery());
queryPS.onRun(preparedStatement);
preparedStatement.execute();
success = true;
} catch (SQLException e) {
e.printStackTrace();
}
return success;
}
@Override
boolean runQuery(QueryRS queryRS) {
boolean success = false;
try {
Connection connection = getConnection();
if (connection == null || connection.isClosed()) {
throw new IllegalStateException("SQL connection is null");
}
@Cleanup PreparedStatement preparedStatement = connection.prepareStatement(queryRS.getQuery());
queryRS.onRun(preparedStatement);
preparedStatement.execute();
@Cleanup ResultSet resultSet = preparedStatement.executeQuery();
success = queryRS.onResult(resultSet);
} catch (SQLException e) {
e.printStackTrace();
}
return success;
}
@Override
public void shutdown() {
try {
if (connection != null && !connection.isClosed()) {
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
@Override
Connection getConnection() throws SQLException {
if (connection == null || connection.isClosed()) {
try {
Class.forName("org.h2.Driver");
} catch (ClassNotFoundException ignored) {}
connection = DriverManager.getConnection("jdbc:h2:" + file.getAbsolutePath());
}
return connection;
}
}
@@ -0,0 +1,453 @@
/*
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.storage.methods;
import com.mongodb.MongoClient;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.InsertOneOptions;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.api.LogEntry;
import me.lucko.luckperms.data.Log;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.groups.GroupManager;
import me.lucko.luckperms.storage.Datastore;
import me.lucko.luckperms.storage.DatastoreConfiguration;
import me.lucko.luckperms.tracks.Track;
import me.lucko.luckperms.tracks.TrackManager;
import me.lucko.luckperms.users.User;
import org.bson.Document;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.stream.Collectors;
@SuppressWarnings("unchecked")
public class MongoDBDatastore extends Datastore {
private final DatastoreConfiguration configuration;
private MongoClient mongoClient;
private MongoDatabase database;
public MongoDBDatastore(LuckPermsPlugin plugin, DatastoreConfiguration configuration) {
super(plugin, "MongoDB");
this.configuration = configuration;
}
@Override
public void init() {
MongoCredential credential = MongoCredential.createCredential(
configuration.getUsername(),
configuration.getDatabase(),
configuration.getPassword().toCharArray()
);
ServerAddress address = new ServerAddress(
configuration.getAddress().split(":")[0],
Integer.parseInt(configuration.getAddress().split(":")[1])
);
mongoClient = new MongoClient(address, Collections.singletonList(credential));
database = mongoClient.getDatabase(configuration.getDatabase());
setAcceptingLogins(true);
}
@Override
public void shutdown() {
if (mongoClient != null) {
mongoClient.close();
}
}
@Override
public boolean logAction(LogEntry entry) {
return call(() -> {
MongoCollection<Document> c = database.getCollection("action");
Document doc = new Document()
.append("timestamp", entry.getTimestamp())
.append("actor", entry.getActor())
.append("actorName", entry.getActorName())
.append("type", Character.toString(entry.getType()))
.append("actedName", entry.getActedName())
.append("action", entry.getAction());
if (entry.getActed() != null) {
doc.append("acted", entry.getActed());
}
c.insertOne(doc, new InsertOneOptions());
return true;
}, false);
}
@Override
public Log getLog() {
return call(() -> {
final Log.Builder log = Log.builder();
MongoCollection<Document> c = database.getCollection("action");
try (MongoCursor<Document> cursor = c.find().iterator()) {
while (cursor.hasNext()) {
Document d = cursor.next();
UUID actedUuid = null;
if (d.containsKey("acted")) {
actedUuid = d.get("acted", UUID.class);
}
LogEntry e = new LogEntry(
d.getLong("timestamp"),
d.get("actor", UUID.class),
d.getString("actorName"),
d.getString("type").toCharArray()[0],
actedUuid,
d.getString("actedName"),
d.getString("action")
);
log.add(e);
}
}
return log.build();
}, null);
}
@Override
public boolean loadOrCreateUser(UUID uuid, String username) {
User user = plugin.getUserManager().make(uuid, username);
boolean success = call(() -> {
MongoCollection<Document> c = database.getCollection("users");
try (MongoCursor<Document> cursor = c.find(new Document("_id", user.getUuid())).iterator()) {
if (!cursor.hasNext()) {
plugin.getUserManager().giveDefaults(user);
c.insertOne(fromUser(user));
} else {
Document d = cursor.next();
user.setPrimaryGroup(d.getString("primaryGroup"));
user.setNodes(revert((Map<String, Boolean>) d.get("perms")));
if (!d.getString("name").equals(user.getName())) {
c.replaceOne(new Document("_id", user.getUuid()), fromUser(user));
}
}
}
return true;
}, false);
if (success) plugin.getUserManager().updateOrSet(user);
return success;
}
@Override
public boolean loadUser(UUID uuid) {
User user = plugin.getUserManager().make(uuid);
boolean success = call(() -> {
MongoCollection<Document> c = database.getCollection("users");
try (MongoCursor<Document> cursor = c.find(new Document("_id", user.getUuid())).iterator()) {
if (cursor.hasNext()) {
Document d = cursor.next();
user.setName(d.getString("name"));
user.setPrimaryGroup(d.getString("primaryGroup"));
user.setNodes(revert((Map<String, Boolean>) d.get("perms")));
return true;
}
return false;
}
}, false);
if (success) plugin.getUserManager().updateOrSet(user);
return success;
}
@Override
public boolean saveUser(User user) {
return call(() -> {
MongoCollection<Document> c = database.getCollection("users");
c.replaceOne(new Document("_id", user.getUuid()), fromUser(user));
return true;
}, false);
}
@Override
public boolean createAndLoadGroup(String name) {
Group group = plugin.getGroupManager().make(name);
boolean success = call(() -> {
MongoCollection<Document> c = database.getCollection("groups");
try (MongoCursor<Document> cursor = c.find(new Document("_id", group.getName())).iterator()) {
if (!cursor.hasNext()) {
c.insertOne(fromGroup(group));
} else {
Document d = cursor.next();
group.setNodes(revert((Map<String, Boolean>) d.get("perms")));
}
}
return true;
}, false);
if (success) plugin.getGroupManager().updateOrSet(group);
return success;
}
@Override
public boolean loadGroup(String name) {
Group group = plugin.getGroupManager().make(name);
boolean success = call(() -> {
MongoCollection<Document> c = database.getCollection("groups");
try (MongoCursor<Document> cursor = c.find(new Document("_id", group.getName())).iterator()) {
if (cursor.hasNext()) {
Document d = cursor.next();
group.setNodes(revert((Map<String, Boolean>) d.get("perms")));
return true;
}
return false;
}
}, false);
if (success) plugin.getGroupManager().updateOrSet(group);
return success;
}
@Override
public boolean loadAllGroups() {
List<Group> groups = new ArrayList<>();
boolean success = call(() -> {
MongoCollection<Document> c = database.getCollection("groups");
try (MongoCursor<Document> cursor = c.find().iterator()) {
while (cursor.hasNext()) {
Document d = cursor.next();
Group group = plugin.getGroupManager().make(d.getString("_id"));
group.setNodes(revert((Map<String, Boolean>) d.get("perms")));
groups.add(group);
}
}
return true;
}, false);
if (success) {
GroupManager gm = plugin.getGroupManager();
gm.unloadAll();
groups.forEach(gm::set);
}
return success;
}
@Override
public boolean saveGroup(Group group) {
return call(() -> {
MongoCollection<Document> c = database.getCollection("groups");
return c.replaceOne(new Document("_id", group.getName()), fromGroup(group)).wasAcknowledged();
}, false);
}
@Override
public boolean deleteGroup(Group group) {
boolean success = call(() -> {
MongoCollection<Document> c = database.getCollection("groups");
return c.deleteOne(new Document("_id", group.getName())).wasAcknowledged();
}, false);
if (success) plugin.getGroupManager().unload(group);
return success;
}
@Override
public boolean createAndLoadTrack(String name) {
Track track = plugin.getTrackManager().make(name);
boolean success = call(() -> {
MongoCollection<Document> c = database.getCollection("tracks");
try (MongoCursor<Document> cursor = c.find(new Document("_id", track.getName())).iterator()) {
if (!cursor.hasNext()) {
c.insertOne(fromTrack(track));
} else {
Document d = cursor.next();
track.setGroups((List<String>) d.get("groups"));
}
}
return true;
}, false);
if (success) plugin.getTrackManager().updateOrSet(track);
return success;
}
@Override
public boolean loadTrack(String name) {
Track track = plugin.getTrackManager().make(name);
boolean success = call(() -> {
MongoCollection<Document> c = database.getCollection("tracks");
try (MongoCursor<Document> cursor = c.find(new Document("_id", track.getName())).iterator()) {
if (cursor.hasNext()) {
Document d = cursor.next();
track.setGroups((List<String>) d.get("groups"));
return true;
}
return false;
}
}, false);
if (success) plugin.getTrackManager().updateOrSet(track);
return success;
}
@Override
public boolean loadAllTracks() {
List<Track> tracks = new ArrayList<>();
boolean success = call(() -> {
MongoCollection<Document> c = database.getCollection("tracks");
try (MongoCursor<Document> cursor = c.find().iterator()) {
while (cursor.hasNext()) {
Document d = cursor.next();
Track track = plugin.getTrackManager().make(d.getString("_id"));
track.setGroups((List<String>) d.get("groups"));
tracks.add(track);
}
}
return true;
}, false);
if (success) {
TrackManager tm = plugin.getTrackManager();
tm.unloadAll();
tracks.forEach(tm::set);
}
return success;
}
@Override
public boolean saveTrack(Track track) {
return call(() -> {
MongoCollection<Document> c = database.getCollection("tracks");
return c.replaceOne(new Document("_id", track.getName()), fromTrack(track)).wasAcknowledged();
}, false);
}
@Override
public boolean deleteTrack(Track track) {
boolean success = call(() -> {
MongoCollection<Document> c = database.getCollection("tracks");
return c.deleteOne(new Document("_id", track.getName())).wasAcknowledged();
}, false);
if (success) plugin.getTrackManager().unload(track);
return success;
}
@Override
public boolean saveUUIDData(String username, UUID uuid) {
return call(() -> {
MongoCollection<Document> c = database.getCollection("uuid");
try (MongoCursor<Document> cursor = c.find(new Document("_id", uuid)).iterator()) {
if (cursor.hasNext()) {
c.replaceOne(new Document("_id", uuid), new Document("_id", uuid).append("name", username.toLowerCase()));
} else {
c.insertOne(new Document("_id", uuid).append("name", username.toLowerCase()));
}
}
return true;
}, false);
}
@Override
public UUID getUUID(String username) {
return call(() -> {
MongoCollection<Document> c = database.getCollection("uuid");
try (MongoCursor<Document> cursor = c.find(new Document("name", username.toLowerCase())).iterator()) {
if (cursor.hasNext()) {
return cursor.next().get("_id", UUID.class);
}
}
return null;
}, null);
}
private static <T> T call(Callable<T> c, T def) {
try {
return c.call();
} catch (Exception e) {
e.printStackTrace();
return def;
}
}
/* MongoDB does not allow '.' or '$' in key names.
See: https://docs.mongodb.com/manual/reference/limits/#Restrictions-on-Field-Names
The following two methods convert the node maps so they can be stored. */
private static <V> Map<String, V> convert(Map<String, V> map) {
return map.entrySet().stream()
.map(e -> new AbstractMap.SimpleEntry<>(e.getKey().replace(".", "[**DOT**]").replace("$", "[**DOLLAR**]"), e.getValue()))
.collect(Collectors.toMap(AbstractMap.SimpleEntry::getKey, AbstractMap.SimpleEntry::getValue));
}
private static <V> Map<String, V> revert(Map<String, V> map) {
return map.entrySet().stream()
.map(e -> new AbstractMap.SimpleEntry<>(e.getKey().replace("[**DOT**]", ".").replace("[**DOLLAR**]", "$"), e.getValue()))
.collect(Collectors.toMap(AbstractMap.SimpleEntry::getKey, AbstractMap.SimpleEntry::getValue));
}
private static Document fromUser(User user) {
Document main = new Document("_id", user.getUuid())
.append("name", user.getName())
.append("primaryGroup", user.getPrimaryGroup());
Document perms = new Document();
for (Map.Entry<String, Boolean> e : convert(user.getNodes()).entrySet()) {
perms.append(e.getKey(), e.getValue());
}
main.append("perms", perms);
return main;
}
private static Document fromGroup(Group group) {
Document main = new Document("_id", group.getName());
Document perms = new Document();
for (Map.Entry<String, Boolean> e : convert(group.getNodes()).entrySet()) {
perms.append(e.getKey(), e.getValue());
}
main.append("perms", perms);
return main;
}
private static Document fromTrack(Track track) {
return new Document("_id", track.getName()).append("groups", track.getGroups());
}
}
@@ -25,7 +25,7 @@ package me.lucko.luckperms.storage.methods;
import com.zaxxer.hikari.HikariDataSource;
import lombok.Cleanup;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.storage.MySQLConfiguration;
import me.lucko.luckperms.storage.DatastoreConfiguration;
import java.sql.Connection;
import java.sql.PreparedStatement;
@@ -34,16 +34,16 @@ import java.sql.SQLException;
public class MySQLDatastore extends SQLDatastore {
private static final String CREATETABLE_UUID = "CREATE TABLE IF NOT EXISTS `lp_uuid` (`name` VARCHAR(16) NOT NULL, `uuid` VARCHAR(36) NOT NULL, PRIMARY KEY (`name`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;";
private static final String CREATETABLE_USERS = "CREATE TABLE IF NOT EXISTS `lp_users` (`uuid` VARCHAR(36) NOT NULL, `name` VARCHAR(16) NOT NULL, `primary_group` VARCHAR(36) NOT NULL, `perms` TEXT NOT NULL, PRIMARY KEY (`uuid`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;";
private static final String CREATETABLE_GROUPS = "CREATE TABLE IF NOT EXISTS `lp_groups` (`name` VARCHAR(36) NOT NULL, `perms` TEXT NULL, PRIMARY KEY (`name`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;";
private static final String CREATETABLE_TRACKS = "CREATE TABLE IF NOT EXISTS `lp_tracks` (`name` VARCHAR(36) NOT NULL, `groups` TEXT NULL, PRIMARY KEY (`name`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;";
private static final String CREATETABLE_ACTION = "CREATE TABLE IF NOT EXISTS `lp_actions` (`id` INT AUTO_INCREMENT 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, PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;";
private static final String CREATETABLE_UUID = "CREATE TABLE IF NOT EXISTS `lp_uuid` (`name` VARCHAR(16) NOT NULL, `uuid` VARCHAR(36) NOT NULL, PRIMARY KEY (`name`)) DEFAULT CHARSET=utf8;";
private static final String CREATETABLE_USERS = "CREATE TABLE IF NOT EXISTS `lp_users` (`uuid` VARCHAR(36) NOT NULL, `name` VARCHAR(16) NOT NULL, `primary_group` VARCHAR(36) NOT NULL, `perms` TEXT NOT NULL, PRIMARY KEY (`uuid`)) DEFAULT CHARSET=utf8;";
private static final String CREATETABLE_GROUPS = "CREATE TABLE IF NOT EXISTS `lp_groups` (`name` VARCHAR(36) NOT NULL, `perms` TEXT NULL, PRIMARY KEY (`name`)) DEFAULT CHARSET=utf8;";
private static final String CREATETABLE_TRACKS = "CREATE TABLE IF NOT EXISTS `lp_tracks` (`name` VARCHAR(36) NOT NULL, `groups` TEXT NULL, PRIMARY KEY (`name`)) DEFAULT CHARSET=utf8;";
private static final String CREATETABLE_ACTION = "CREATE TABLE IF NOT EXISTS `lp_actions` (`id` INT AUTO_INCREMENT NOT NULL, `time` BIGINT NOT NULL, `actor_uuid` VARCHAR(36) NOT NULL, `actor_name` VARCHAR(16) NOT NULL, `type` CHAR(1) NOT NULL, `acted_uuid` VARCHAR(36) NOT NULL, `acted_name` VARCHAR(36) NOT NULL, `action` VARCHAR(256) NOT NULL, PRIMARY KEY (`id`)) DEFAULT CHARSET=utf8;";
private final MySQLConfiguration configuration;
private final DatastoreConfiguration configuration;
private HikariDataSource hikari;
public MySQLDatastore(LuckPermsPlugin plugin, MySQLConfiguration configuration) {
public MySQLDatastore(LuckPermsPlugin plugin, DatastoreConfiguration configuration) {
super(plugin, "MySQL");
this.configuration = configuration;
}
@@ -66,7 +66,7 @@ public class MySQLDatastore extends SQLDatastore {
hikari.addDataSourceProperty("password", password);
if (!setupTables(CREATETABLE_UUID, CREATETABLE_USERS, CREATETABLE_GROUPS, CREATETABLE_TRACKS, CREATETABLE_ACTION)) {
plugin.getLog().severe("Error occurred whilst initialising the database. All connections are disallowed.");
plugin.getLog().severe("Error occurred whilst initialising the database.");
shutdown();
} else {
setAcceptingLogins(true);
@@ -109,7 +109,7 @@ abstract class SQLDatastore extends Datastore {
boolean onResult(ResultSet resultSet) throws SQLException {
if (resultSet.next()) {
user.setName(resultSet.getString("name"));
user.getNodes().putAll(gson.fromJson(resultSet.getString("perms"), NM_TYPE));
user.setNodes(gson.fromJson(resultSet.getString("perms"), NM_TYPE));
user.setPrimaryGroup(resultSet.getString("primary_group"));
return true;
}
@@ -193,7 +193,7 @@ abstract class SQLDatastore extends Datastore {
}
});
} else {
user.getNodes().putAll(gson.fromJson(resultSet.getString("perms"), NM_TYPE));
user.setNodes(gson.fromJson(resultSet.getString("perms"), NM_TYPE));
user.setPrimaryGroup(resultSet.getString("primary_group"));
if (!resultSet.getString("name").equals(user.getName())) {
@@ -251,7 +251,7 @@ abstract class SQLDatastore extends Datastore {
}
});
} else {
group.getNodes().putAll(gson.fromJson(resultSet.getString("perms"), NM_TYPE));
group.setNodes(gson.fromJson(resultSet.getString("perms"), NM_TYPE));
}
return success;
}
@@ -273,7 +273,7 @@ abstract class SQLDatastore extends Datastore {
@Override
boolean onResult(ResultSet resultSet) throws SQLException {
if (resultSet.next()) {
group.getNodes().putAll(gson.fromJson(resultSet.getString("perms"), NM_TYPE));
group.setNodes(gson.fromJson(resultSet.getString("perms"), NM_TYPE));
return true;
}
return false;
@@ -297,7 +297,7 @@ abstract class SQLDatastore extends Datastore {
boolean onResult(ResultSet resultSet) throws SQLException {
while (resultSet.next()) {
Group group = plugin.getGroupManager().make(resultSet.getString("name"));
group.getNodes().putAll(gson.fromJson(resultSet.getString("perms"), NM_TYPE));
group.setNodes(gson.fromJson(resultSet.getString("perms"), NM_TYPE));
groups.add(group);
}
return true;
@@ -47,7 +47,7 @@ public class SQLiteDatastore extends SQLDatastore {
@Override
public void init() {
if (!setupTables(CREATETABLE_UUID, CREATETABLE_USERS, CREATETABLE_GROUPS, CREATETABLE_TRACKS, CREATETABLE_ACTION)) {
plugin.getLog().severe("Error occurred whilst initialising the database. All connections are disallowed.");
plugin.getLog().severe("Error occurred whilst initialising the database.");
shutdown();
} else {
setAcceptingLogins(true);
Loaded 100 of 114 files, more files were not shown because too many files have changed in this diff. Show more