Skip to content

Commit

Permalink
feat: re-implement permissions
Browse files Browse the repository at this point in the history
  • Loading branch information
ZakShearman committed Nov 30, 2024
1 parent bf190ce commit fdd1be7
Show file tree
Hide file tree
Showing 12 changed files with 149 additions and 11 deletions.
4 changes: 3 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ repositories {

dependencies {
// Minestom
api("net.minestom:minestom-snapshots:c148954a47")
api("net.minestom:minestom-snapshots:1_21_2-0b0a3aba23")
api("net.kyori:adventure-text-minimessage:4.15.0")
compileOnly("com.github.TogAr2:MinestomPvP:04180ddf9a") // MinestomPvP - Used for PvP Player impl

implementation("io.pyroscope:agent:0.14.0")

// Logger
Expand Down
7 changes: 6 additions & 1 deletion src/main/java/dev/emortal/minestom/core/EntrypointTest.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package dev.emortal.minestom.core;

import dev.emortal.minestom.core.module.monitoring.MonitoringModule;
import dev.emortal.minestom.core.module.permissions.PermissionHolder;
import net.minestom.server.MinecraftServer;
import net.minestom.server.command.CommandManager;
import net.minestom.server.command.builder.Command;
Expand Down Expand Up @@ -51,7 +52,11 @@ public static void main(String[] args) {
command.addSyntax((sender, context) -> sender.sendMessage("Hello world 2!"), required, optional);

Command testPermsCmd = new Command("testperms");
testPermsCmd.setCondition((sender, commandName) -> sender.hasPermission("command.testperms"));
testPermsCmd.setCondition((sender, commandName) -> {
if (!(sender instanceof PermissionHolder permHolder)) return false;

return permHolder.hasPermission("command.testperms");
});
testPermsCmd.setDefaultExecutor((sender, context) -> sender.sendMessage("works :)"));

CommandManager commandManager = MinecraftServer.getCommandManager();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public boolean onLoad() {

Player player = event.getPlayer();
var message = ChatMessage.newBuilder()
.setMessage(event.getMessage())
.setMessage(event.getRawMessage())
.setSenderId(player.getUuid().toString())
.setSenderUsername(player.getUsername())
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import dev.emortal.minestom.core.module.MinestomModule;
import dev.emortal.minestom.core.module.core.badge.BadgeCommand;
import dev.emortal.minestom.core.module.core.performance.PerformanceCommand;
import dev.emortal.minestom.core.module.core.playerprovider.EmortalPlayerImpl;
import dev.emortal.minestom.core.utils.resolver.PlayerResolver;
import net.minestom.server.MinecraftServer;
import net.minestom.server.command.CommandManager;
Expand All @@ -21,6 +22,8 @@ public CoreModule(@NotNull ModuleEnvironment environment) {

@Override
public boolean onLoad() {
MinecraftServer.getConnectionManager().setPlayerProvider(EmortalPlayerImpl::new);

McPlayerService playerService = GrpcStubCollection.getPlayerService().orElse(null);
PlayerResolver playerResolver = new PlayerResolver(playerService, MinecraftServer.getConnectionManager());

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package dev.emortal.minestom.core.module.core.playerprovider;

import dev.emortal.minestom.core.module.permissions.Permission;
import io.github.togar2.pvp.player.CombatPlayerImpl;
import net.minestom.server.network.player.PlayerConnection;
import org.jetbrains.annotations.NotNull;

import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArraySet;

// This class should be instantiated instead of CombatPlayerImpl by any games that use the Emortal API
@SuppressWarnings("unused")
public class EmortalCombatPlayer extends CombatPlayerImpl implements EmortalPlayer {
private final @NotNull Set<Permission> permissions = new CopyOnWriteArraySet<>();

public EmortalCombatPlayer(@NotNull UUID uuid, @NotNull String username, @NotNull PlayerConnection playerConnection) {
super(uuid, username, playerConnection);
}

@Override
public @NotNull Set<Permission> getPermissions() {
return this.permissions;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package dev.emortal.minestom.core.module.core.playerprovider;

import dev.emortal.minestom.core.module.permissions.PermissionHolder;

public interface EmortalPlayer extends PermissionHolder {


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package dev.emortal.minestom.core.module.core.playerprovider;

import dev.emortal.minestom.core.module.permissions.Permission;
import dev.emortal.minestom.core.module.permissions.PermissionHolder;
import net.minestom.server.entity.Player;
import net.minestom.server.network.player.GameProfile;
import net.minestom.server.network.player.PlayerConnection;
import org.jetbrains.annotations.NotNull;

import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;

public class EmortalPlayerImpl extends Player implements EmortalPlayer {
private final @NotNull Set<Permission> permissions = new CopyOnWriteArraySet<>();

public EmortalPlayerImpl(@NotNull PlayerConnection playerConnection, @NotNull GameProfile gameProfile) {
super(playerConnection, gameProfile);
}

@Override
public @NotNull Set<Permission> getPermissions() {
return this.permissions;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package dev.emortal.minestom.core.module.permissions;

import org.jetbrains.annotations.NotNull;

public record Permission(@NotNull String permission, boolean state) {

public Permission(@NotNull String permission) {
this(permission, true);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import net.minestom.server.event.EventNode;
import net.minestom.server.event.player.AsyncPlayerConfigurationEvent;
import net.minestom.server.event.player.PlayerDisconnectEvent;
import net.minestom.server.permission.Permission;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -65,6 +64,8 @@ private void loadRoles() {
* @param player the player to load
*/
private void loadUser(@NotNull Player player) {
PermissionHolder permHolder = (PermissionHolder) player;

PlayerRolesResponse response;
try {
response = this.permissionService.getPlayerRoles(player.getUuid());
Expand All @@ -85,8 +86,8 @@ private void loadUser(@NotNull Player player) {
permissions.addAll(role.permissions());
}

player.getAllPermissions().clear();
player.getAllPermissions().addAll(permissions);
permHolder.getPermissions().clear();
permHolder.getPermissions().addAll(permissions);
}

private void updateUserPermissions(@NotNull User user) {
Expand All @@ -95,11 +96,12 @@ private void updateUserPermissions(@NotNull User user) {
LOGGER.error("Couldn't find player with id {}", user.id());
return;
}
PermissionHolder permHolder = (PermissionHolder) player;

Set<Permission> permissions = this.calculatePerms(user.roleIds());
this.userCache.put(user.id(), user);
player.getAllPermissions().clear();
player.getAllPermissions().addAll(permissions);
permHolder.getPermissions().clear();
permHolder.getPermissions().addAll(permissions);

player.refreshCommands();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package dev.emortal.minestom.core.module.permissions;

import org.jetbrains.annotations.NotNull;

import java.util.Set;
import java.util.regex.Pattern;

public interface PermissionHolder {

@NotNull Set<Permission> getPermissions();

default void addPermission(@NotNull Permission permission) {
this.getPermissions().add(permission);
}

default void removePermission(@NotNull Permission permission) {
this.getPermissions().remove(permission);
}

default void removePermission(@NotNull String permission) {
this.getPermissions().removeIf(p -> p.permission().equals(permission));
}

default boolean hasPermission(@NotNull Permission permission) {
for (Permission permissionLoop : this.getPermissions()) {
if (permissionLoop.equals(permission)) {
return true;
}
String permissionLoopName = permissionLoop.permission();
if (permissionLoopName.contains("*")) {
// Sanitize permissionLoopName
String regexSanitized = Pattern.quote(permissionLoopName).replace("*", "\\E(.*)\\Q"); // Replace * with regex
// pattern matching for wildcards, where foo.b*r.baz matches foo.baaaar.baz or foo.bar.baz
if (permission.permission().matches(regexSanitized)) {
return true;
}
}
}
return false;
}

default boolean hasPermission(@NotNull String permission) {
return this.hasPermission(new Permission(permission, true));
}

default Permission getPermission(@NotNull String permission) {
for (Permission permissionLoop : this.getPermissions()) {
if (permissionLoop.permission().equals(permission)) {
return permissionLoop;
}
}

return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import dev.emortal.minestom.core.module.MinestomModule;
import dev.emortal.minestom.core.module.messaging.MessagingModule;
import net.minestom.server.event.player.AsyncPlayerConfigurationEvent;
import net.minestom.server.permission.Permission;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
Expand All @@ -34,7 +33,7 @@ public boolean onLoad() {
if (!ENABLED) {
if (GRANT_ALL_PERMISSIONS) {
LOGGER.warn("Permission service is not available, granting all permissions");
this.eventNode.addListener(AsyncPlayerConfigurationEvent.class, event -> event.getPlayer().addPermission(new Permission("*")));
this.eventNode.addListener(AsyncPlayerConfigurationEvent.class, event -> ((PermissionHolder) event.getPlayer()).addPermission(new Permission("*")));
} else {
LOGGER.warn("Permission service is not available, denying all permissions");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
package dev.emortal.minestom.core.utils.command;

import dev.emortal.minestom.core.module.permissions.PermissionHolder;
import net.minestom.server.command.builder.condition.CommandCondition;
import org.jetbrains.annotations.NotNull;

public final class ExtraConditions {

public static @NotNull CommandCondition hasPermission(@NotNull String permission) {
return (sender, commandName) -> sender.hasPermission(permission);
return (sender, commandName) -> {
if (!(sender instanceof PermissionHolder permHolder)) return false;
return permHolder.hasPermission(permission);
};
}

private ExtraConditions() {
Expand Down

0 comments on commit fdd1be7

Please sign in to comment.