Start of Permission API

This commit is contained in:
jglrxavpok 2020-07-31 22:31:58 +02:00
parent aada943f91
commit 1772b94114
7 changed files with 232 additions and 0 deletions

View File

@ -34,6 +34,10 @@ sourceSets {
}
}
test {
useJUnitPlatform()
}
dependencies {
// Junit Testing Framework
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.6.2'

View File

@ -1,6 +1,9 @@
package net.minestom.server.command;
import net.minestom.server.entity.Player;
import net.minestom.server.permission.Permission;
import java.util.Collection;
/**
* Represent something which can send commands to the server
@ -27,6 +30,62 @@ public interface CommandSender {
}
}
/**
* Return all permissions associated to this command sender.
* The returned collection should be modified only by subclasses
* @return
*/
Collection<Permission> getAllPermissions();
/**
* Adds a permission to this commandSender
* @param permission
*/
default void addPermission(Permission permission) {
getAllPermissions().add(permission);
}
/**
* Removes a permission from this commandSender
* @param permission
*/
default void removePermission(Permission permission) {
getAllPermissions().remove(permission);
}
/**
* Checks if the given permission is possessed by this command sender.
* Simple shortcut to <pre>getAllPermissions().contains(permission)</pre> for readability.
* @param p permission to check against
* @return
*/
default boolean hasPermission(Permission p) {
return getAllPermissions().contains(p);
}
/**
* Checks if the given permission is possessed by this command sender.
* Will call {@link #hasPermission(Permission)} on all permissions that are an instance of permissionClass.
* If no matching permission is found, this result returns false.
*
* @param permissionClass
* @see #getAllPermissions()
* @return
*/
default boolean hasPermission(Class<? extends Permission> permissionClass) {
boolean result = true;
boolean foundPerm = false;
for(Permission p : getAllPermissions()) {
if(permissionClass.isInstance(p)) {
foundPerm = true;
result &= p.isValidFor(this);
}
}
if(!foundPerm)
return false;
return result;
}
/**
* Get if the sender is a player
*
@ -45,4 +104,21 @@ public interface CommandSender {
return this instanceof ConsoleSender;
}
/**
* Casts this object to a Player
* No checks are performed, {@link ClassCastException} can very much happen
* @see #isPlayer()
*/
default Player asPlayer() {
return (Player)this;
}
/**
* Casts this object to a ConsoleSender
* No checks are performed, {@link ClassCastException} can very much happen
* @see #isConsole()
*/
default ConsoleSender asConsole() {
return (ConsoleSender)this;
}
}

View File

@ -1,12 +1,25 @@
package net.minestom.server.command;
import net.minestom.server.permission.Permission;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
/**
* Represent the console when sending a command to the server
*/
public class ConsoleSender implements CommandSender {
private final List<Permission> permissions = new LinkedList<>();
@Override
public void sendMessage(String message) {
System.out.println(message);
}
@Override
public Collection<Permission> getAllPermissions() {
return permissions;
}
}

View File

@ -31,6 +31,7 @@ import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.login.JoinGamePacket;
import net.minestom.server.network.packet.server.play.*;
import net.minestom.server.network.player.PlayerConnection;
import net.minestom.server.permission.Permission;
import net.minestom.server.recipe.Recipe;
import net.minestom.server.recipe.RecipeManager;
import net.minestom.server.resourcepack.ResourcePack;
@ -138,6 +139,8 @@ public class Player extends LivingEntity implements CommandSender {
// Tick related
private final PlayerTickEvent playerTickEvent = new PlayerTickEvent(this);
private final List<Permission> permissions = new LinkedList<>();
public Player(UUID uuid, String username, PlayerConnection playerConnection) {
super(EntityType.PLAYER);
this.uuid = uuid; // Override Entity#uuid defined in the constructor
@ -627,6 +630,11 @@ public class Player extends LivingEntity implements CommandSender {
sendMessage(ColoredText.of(message));
}
@Override
public Collection<Permission> getAllPermissions() {
return permissions;
}
/**
* Send a message to the player
*

View File

@ -0,0 +1,14 @@
package net.minestom.server.permission;
import net.minestom.server.command.CommandSender;
/**
* Basic Permission implementation that only requires the permission to be given to a player to be considered applied
* (eg. no arguments)
*/
public class BasicPermission implements Permission {
@Override
public boolean isValidFor(CommandSender commandSender) {
return true;
}
}

View File

@ -0,0 +1,18 @@
package net.minestom.server.permission;
import net.minestom.server.command.CommandSender;
/**
* Representation of a permission granted to a CommandSender
*/
public interface Permission {
/**
* Does the given commandSender have the permission represented by this object?
* @param commandSender
* @return true if the commandSender possesses this permission
*/
boolean isValidFor(CommandSender commandSender);
// TODO: Serialization?
}

View File

@ -0,0 +1,99 @@
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 org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.UUID;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
// TODO: more tests
public class TestPermissions {
private Player player;
@BeforeEach
public void init() {
MinecraftServer.init(); // for entity manager
player = new Player(UUID.randomUUID(), "TestPlayer", null) {
@Override
protected void playerConnectionInit() {}
@Override
public boolean isOnline() {
return false;
}
};
}
@Test
public void noPermission() {
assertFalse(player.hasPermission(Permission.class));
}
class PermTest1 implements Permission {
@Override
public boolean isValidFor(CommandSender commandSender) {
return true;
}
}
class PermTest2 implements Permission {
@Override
public boolean isValidFor(CommandSender commandSender) {
return true;
}
}
@Test
public void hasPermissionClass() {
assertFalse(player.hasPermission(Permission.class));
player.addPermission(new PermTest1());
assertTrue(player.hasPermission(PermTest1.class));
assertFalse(player.hasPermission(PermTest2.class));
assertTrue(player.hasPermission(Permission.class)); // allow superclasses
player.addPermission(new PermTest2());
assertTrue(player.hasPermission(PermTest2.class));
}
class BooleanPerm implements Permission {
private final boolean value;
BooleanPerm(boolean v) {
this.value = v;
}
@Override
public boolean isValidFor(CommandSender commandSender) {
return value;
}
}
@Test
public void hasTwoPermissionsOfSameClassButContradictEachOther() {
player.addPermission(new BooleanPerm(true));
assertTrue(player.hasPermission(BooleanPerm.class));
player.addPermission(new BooleanPerm(false));
assertFalse(player.hasPermission(BooleanPerm.class)); // all permissions must be valid
}
@Test
public void singlePermission() {
Permission p = commandSender -> true;
player.addPermission(p);
assertTrue(p.isValidFor(player));
assertTrue(player.hasPermission(p));
assertTrue(player.hasPermission(Permission.class));
}
@AfterEach
public void cleanup() {
}
}