Created PermissionHandler

This commit is contained in:
themode 2020-11-14 07:06:46 +01:00
parent 868f921b94
commit da94942bad
10 changed files with 116 additions and 102 deletions

View File

@ -83,6 +83,7 @@ public final class CommandManager {
* Registers a {@link Command}.
*
* @param command the command to register
* @throws IllegalStateException if a command with the same name already exists
*/
public synchronized void register(@NotNull Command command) {
Check.stateCondition(commandExists(command.getName()),
@ -109,6 +110,7 @@ public final class CommandManager {
* Registers a {@link CommandProcessor}.
*
* @param commandProcessor the command to register
* @throws IllegalStateException if a command with the same name already exists
*/
public synchronized void register(@NotNull CommandProcessor commandProcessor) {
final String commandName = commandProcessor.getCommandName().toLowerCase();

View File

@ -12,6 +12,8 @@ import org.jetbrains.annotations.Nullable;
* <p>
* Tab-completion can be activated by overriding {@link #enableWritingTracking()} and return true, you should then listen to
* {@link #onWrite(String)} and return the possible completions to suggest.
* <p>
* Please be sure to check {@link net.minestom.server.command.builder.Command} as it is likely to be better for your use case.
*/
public interface CommandProcessor {

View File

@ -1,18 +1,15 @@
package net.minestom.server.command;
import net.minestom.server.entity.Player;
import net.minestom.server.permission.Permission;
import net.minestom.server.permission.PermissionHandler;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
/**
* Represents something which can send commands to the server.
* <p>
* Main implementations are {@link Player} and {@link ConsoleSender}.
*/
public interface CommandSender {
public interface CommandSender extends PermissionHandler {
/**
* Sends a raw string message.
@ -32,85 +29,6 @@ public interface CommandSender {
}
}
/**
* Returns all permissions associated to this command sender.
* The returned collection should be modified only by subclasses.
*
* @return the permissions of this command sender.
*/
@NotNull
Collection<Permission> getAllPermissions();
/**
* Adds a {@link Permission} to this commandSender
*
* @param permission the permission to add
*/
default void addPermission(@NotNull Permission permission) {
getAllPermissions().add(permission);
}
/**
* Removes a {@link Permission} from this commandSender
*
* @param permission the permission to remove
*/
default void removePermission(@NotNull Permission permission) {
getAllPermissions().remove(permission);
}
/**
* Checks if the given {@link Permission} is possessed by this command sender.
* Simple shortcut to <pre>getAllPermissions().contains(permission) &amp;&amp; permission.isValidFor(this)</pre> for readability.
*
* @param p permission to check against
* @return true if the sender has the permission and validate {@link Permission#isValidFor(CommandSender, Object)}
*/
default boolean hasPermission(@NotNull Permission p) {
return hasPermission(p, null);
}
default <T> boolean hasPermission(@NotNull Permission<T> p, @Nullable T data) {
return getAllPermissions().contains(p) && p.isValidFor(this, data);
}
/**
* Checks if the given {@link Permission} is possessed by this command sender.
* Will call {@link Permission#isValidFor(CommandSender, Object)} on all permissions that are an instance of {@code permissionClass}.
* If no matching permission is found, this result returns false.
*
* @param permissionClass the permission class to check
* @return true if the sender has the permission and validate {@link Permission#isValidFor(CommandSender, Object)}
* @see #getAllPermissions()
*/
default boolean hasPermission(@NotNull Class<? extends Permission> permissionClass) {
boolean result = true;
boolean foundPerm = false;
for (Permission p : getAllPermissions()) {
if (permissionClass.isInstance(p)) {
foundPerm = true;
result &= p.isValidFor(this, null);
}
}
if (!foundPerm)
return false;
return result;
}
default <T> boolean hasPermission(@NotNull Class<? extends Permission<T>> permissionClass, @Nullable T data) {
boolean result = true;
boolean foundPerm = false;
for (Permission p : getAllPermissions()) {
if (permissionClass.isInstance(p)) {
foundPerm = true;
result &= p.isValidFor(this, data);
}
}
if (!foundPerm)
return false;
return result;
}
/**
* Gets if the sender is a {@link Player}.
*

View File

@ -58,7 +58,7 @@ public class Command {
}
/**
* Creates a {@link Command} with a name without any aliases.
* Creates a {@link Command} with a name and no alias.
*
* @param name the name of the command
* @see #Command(String, String...)
@ -70,8 +70,10 @@ public class Command {
/**
* Gets the {@link CommandCondition}.
* <p>
* It is called no matter the syntax used and can be used to check permissions or
* It is called after the parsing and just before the execution no matter the syntax used and can be used to check permissions or
* the {@link CommandSender} type.
* <p>
* Worth mentioning that the condition is also used to know if the command known from a player (at connection).
*
* @return the command condition, null if not any
*/
@ -84,6 +86,7 @@ public class Command {
* Sets the {@link CommandCondition}.
*
* @param commandCondition the new command condition, null to do not call anything
* @see #getCondition()
*/
public void setCondition(@Nullable CommandCondition commandCondition) {
this.condition = commandCondition;
@ -104,7 +107,7 @@ public class Command {
/**
* Adds a new syntax in the command.
* <p>
* A syntax is simply a list of arguments.
* A syntax is simply a list of arguments and an executor called when successfully parsed.
*
* @param commandCondition the condition to use the syntax
* @param executor the executor to call when the syntax is successfully received

View File

@ -10,18 +10,14 @@ import net.minestom.server.network.PacketProcessor;
import net.minestom.server.network.netty.packet.InboundPacket;
import net.minestom.server.network.player.PlayerConnection;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Slf4j
public class ClientChannel extends SimpleChannelInboundHandler<InboundPacket> {
public final static Logger LOGGER = LoggerFactory.getLogger(ClientChannel.class);
private final ConnectionManager connectionManager = MinecraftServer.getConnectionManager();
private final PacketProcessor packetProcessor;
public ClientChannel(PacketProcessor packetProcessor) {
public ClientChannel(@NotNull PacketProcessor packetProcessor) {
this.packetProcessor = packetProcessor;
}
@ -40,7 +36,7 @@ public class ClientChannel extends SimpleChannelInboundHandler<InboundPacket> {
if (availableBytes > 0) {
final PlayerConnection playerConnection = packetProcessor.getPlayerConnection(ctx);
LOGGER.warn("WARNING: Packet 0x" + Integer.toHexString(packet.packetId)
log.warn("WARNING: Packet 0x" + Integer.toHexString(packet.packetId)
+ " not fully read (" + availableBytes + " bytes left), " + playerConnection);
packet.body.skipBytes(availableBytes);

View File

@ -39,6 +39,7 @@ public class HandshakePacket implements ClientPreplayPacket {
@Override
public void process(@NotNull PlayerConnection connection) {
// Bungee support (IP forwarding)
if (BungeeCordProxy.isEnabled() && connection instanceof NettyPlayerConnection) {
NettyPlayerConnection nettyPlayerConnection = (NettyPlayerConnection) connection;

View File

@ -9,7 +9,7 @@ import org.jetbrains.annotations.NotNull;
*/
public class BasicPermission implements Permission<Object> {
@Override
public boolean isValidFor(@NotNull CommandSender commandSender, Object data) {
public boolean isValidFor(@NotNull PermissionHandler permissionHandler, Object data) {
return true;
}
}

View File

@ -8,7 +8,7 @@ import org.jetbrains.annotations.Nullable;
/**
* Representation of a permission granted to a {@link CommandSender}.
*
* @param <T> the type of data that this permission can handle in {@link #isValidFor(CommandSender, Object)}.
* @param <T> the type of data that this permission can handle in {@link #isValidFor(PermissionHandler, Object)}.
* Used if you want to allow passing additional data to check if the permission is valid in a certain situation,
* you can default it to {@link Object} if you do not need it.
*/
@ -21,11 +21,11 @@ public interface Permission<T> {
* Called with {@link CommandSender#hasPermission(Permission)}, the {@link CommandSender} requires to both
* have this permission and validate the condition in this method.
*
* @param commandSender the command sender
* @param data the optional data (eg the number of home possible, placing a block at X position)
* @param permissionHandler the permission handler
* @param data the optional data (eg the number of home possible, placing a block at X position)
* @return true if the commandSender possesses this permission
*/
boolean isValidFor(@NotNull CommandSender commandSender, @Nullable T data);
boolean isValidFor(@NotNull PermissionHandler permissionHandler, @Nullable T data);
/**
* Writes any required data for this permission inside the given destination.

View File

@ -0,0 +1,92 @@
package net.minestom.server.permission;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
/**
* Represents an object which can have permissions.
*/
public interface PermissionHandler {
/**
* Returns all permissions associated to this command sender.
* The returned collection should be modified only by subclasses.
*
* @return the permissions of this command sender.
*/
@NotNull
Collection<Permission> getAllPermissions();
/**
* Adds a {@link Permission} to this commandSender
*
* @param permission the permission to add
*/
default void addPermission(@NotNull Permission permission) {
getAllPermissions().add(permission);
}
/**
* Removes a {@link Permission} from this commandSender
*
* @param permission the permission to remove
*/
default void removePermission(@NotNull Permission permission) {
getAllPermissions().remove(permission);
}
/**
* Checks if the given {@link Permission} is possessed by this command sender.
* Simple shortcut to <pre>getAllPermissions().contains(permission) &amp;&amp; permission.isValidFor(this)</pre> for readability.
*
* @param p permission to check against
* @return true if the sender has the permission and validate {@link Permission#isValidFor(PermissionHandler, Object)}
*/
default boolean hasPermission(@NotNull Permission p) {
return hasPermission(p, null);
}
default <T> boolean hasPermission(@NotNull Permission<T> p, @Nullable T data) {
return getAllPermissions().contains(p) && p.isValidFor(this, data);
}
/**
* Checks if the given {@link Permission} is possessed by this command sender.
* Will call {@link Permission#isValidFor(PermissionHandler, Object)} on all permissions that are an instance of {@code permissionClass}.
* If no matching permission is found, this result returns false.
*
* @param permissionClass the permission class to check
* @return true if the sender has the permission and validate {@link Permission#isValidFor(PermissionHandler, Object)}
* @see #getAllPermissions()
*/
default boolean hasPermission(@NotNull Class<? extends Permission> permissionClass) {
boolean result = true;
boolean foundPerm = false;
for (Permission p : getAllPermissions()) {
if (permissionClass.isInstance(p)) {
foundPerm = true;
result &= p.isValidFor(this, null);
}
}
if (!foundPerm)
return false;
return result;
}
default <T> boolean hasPermission(@NotNull Class<? extends Permission<T>> permissionClass, @Nullable T data) {
boolean result = true;
boolean foundPerm = false;
for (Permission p : getAllPermissions()) {
if (permissionClass.isInstance(p)) {
foundPerm = true;
result &= p.isValidFor(this, data);
}
}
if (!foundPerm)
return false;
return result;
}
}

View File

@ -1,9 +1,9 @@
package permissions;
import net.minestom.server.MinecraftServer;
import net.minestom.server.command.CommandSender;
import net.minestom.server.entity.Player;
import net.minestom.server.permission.Permission;
import net.minestom.server.permission.PermissionHandler;
import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
@ -41,14 +41,14 @@ public class TestPermissions {
class PermTest1 implements Permission<Object> {
@Override
public boolean isValidFor(@NotNull CommandSender commandSender, Object data) {
public boolean isValidFor(@NotNull PermissionHandler permissionHandler, Object data) {
return true;
}
}
class PermTest2 implements Permission<Object> {
@Override
public boolean isValidFor(@NotNull CommandSender commandSender, Object data) {
public boolean isValidFor(@NotNull PermissionHandler permissionHandler, Object data) {
return true;
}
}
@ -73,7 +73,7 @@ public class TestPermissions {
}
@Override
public boolean isValidFor(@NotNull CommandSender commandSender, Object data) {
public boolean isValidFor(@NotNull PermissionHandler permissionHandler, Object data) {
return value;
}
}