mirror of
https://github.com/Melledy/LunarCore.git
synced 2025-12-14 14:24:37 +01:00
Implement permission system for commands
This commit is contained in:
@@ -1,5 +1,8 @@
|
|||||||
package emu.lunarcore;
|
package emu.lunarcore;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@@ -15,6 +18,7 @@ public class Config {
|
|||||||
public ServerConfig httpServer = new ServerConfig("127.0.0.1", 443);
|
public ServerConfig httpServer = new ServerConfig("127.0.0.1", 443);
|
||||||
public GameServerConfig gameServer = new GameServerConfig("127.0.0.1", 23301);
|
public GameServerConfig gameServer = new GameServerConfig("127.0.0.1", 23301);
|
||||||
|
|
||||||
|
public ServerOptions serverOptions = new ServerOptions();
|
||||||
public DownloadData downloadData = new DownloadData();
|
public DownloadData downloadData = new DownloadData();
|
||||||
|
|
||||||
public String resourceDir = "./resources";
|
public String resourceDir = "./resources";
|
||||||
@@ -70,6 +74,12 @@ public class Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public static class ServerOptions {
|
||||||
|
public int entitySceneLimit = 2000;
|
||||||
|
public Set<String> defaultPermissions = Set.of("*");
|
||||||
|
}
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
public static class DownloadData {
|
public static class DownloadData {
|
||||||
public String assetBundleUrl = null;
|
public String assetBundleUrl = null;
|
||||||
|
|||||||
@@ -10,4 +10,6 @@ public @interface Command {
|
|||||||
public String[] aliases() default "";
|
public String[] aliases() default "";
|
||||||
|
|
||||||
public String desc() default "";
|
public String desc() default "";
|
||||||
|
|
||||||
|
public String permission() default "";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ public class CommandArgs {
|
|||||||
|
|
||||||
private int targetUid;
|
private int targetUid;
|
||||||
private int level;
|
private int level;
|
||||||
private int count;
|
private int amount;
|
||||||
private int rank;
|
private int rank;
|
||||||
private int promotion;
|
private int promotion;
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ public class CommandArgs {
|
|||||||
this.targetUid = Utils.parseSafeInt(arg.substring(1));
|
this.targetUid = Utils.parseSafeInt(arg.substring(1));
|
||||||
it.remove();
|
it.remove();
|
||||||
} else if (arg.startsWith("x")) {
|
} else if (arg.startsWith("x")) {
|
||||||
this.count = Utils.parseSafeInt(arg.substring(1));
|
this.amount = Utils.parseSafeInt(arg.substring(1));
|
||||||
it.remove();
|
it.remove();
|
||||||
} else if (arg.startsWith("lv")) {
|
} else if (arg.startsWith("lv")) {
|
||||||
this.level = Utils.parseSafeInt(arg.substring(2));
|
this.level = Utils.parseSafeInt(arg.substring(2));
|
||||||
|
|||||||
@@ -77,6 +77,22 @@ public class CommandManager {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean checkPermission(Player sender, Command command) {
|
||||||
|
if (sender == null || command.permission().isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sender.getAccount().hasPermission(command.permission());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean checkTargetPermission(Player sender, Command command) {
|
||||||
|
if (sender == null || command.permission().isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sender.getAccount().hasPermission("target." + command.permission());
|
||||||
|
}
|
||||||
|
|
||||||
public void invoke(Player sender, String message) {
|
public void invoke(Player sender, String message) {
|
||||||
List<String> args = Arrays.stream(message.split(" ")).collect(Collectors.toCollection(ArrayList::new));
|
List<String> args = Arrays.stream(message.split(" ")).collect(Collectors.toCollection(ArrayList::new));
|
||||||
|
|
||||||
@@ -89,8 +105,24 @@ public class CommandManager {
|
|||||||
|
|
||||||
// Get handler
|
// Get handler
|
||||||
CommandHandler handler = this.commands.get(label);
|
CommandHandler handler = this.commands.get(label);
|
||||||
|
|
||||||
|
// Execute
|
||||||
if (handler != null) {
|
if (handler != null) {
|
||||||
handler.execute(sender, new CommandArgs(sender, args));
|
// Command annotation data
|
||||||
|
Command command = handler.getClass().getAnnotation(Command.class);
|
||||||
|
// Check permission
|
||||||
|
if (this.checkPermission(sender, command)) {
|
||||||
|
// Check targetted permission
|
||||||
|
CommandArgs cmdArgs = new CommandArgs(sender, args);
|
||||||
|
if (sender != cmdArgs.getTarget() && !this.checkTargetPermission(sender, command)) {
|
||||||
|
handler.sendMessage(sender, "You do not have permission to use this command on another player");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Run command
|
||||||
|
handler.execute(sender, cmdArgs);
|
||||||
|
} else {
|
||||||
|
handler.sendMessage(sender, "You do not have permission to use this command");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (sender != null) {
|
if (sender != null) {
|
||||||
sender.sendMessage("Inavlid Command!");
|
sender.sendMessage("Inavlid Command!");
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import emu.lunarcore.game.account.AccountHelper;
|
|||||||
import emu.lunarcore.game.player.Player;
|
import emu.lunarcore.game.player.Player;
|
||||||
import emu.lunarcore.util.Utils;
|
import emu.lunarcore.util.Utils;
|
||||||
|
|
||||||
@Command(label = "account")
|
@Command(label = "account", permission = "server.account")
|
||||||
public class AccountCommand implements CommandHandler {
|
public class AccountCommand implements CommandHandler {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import emu.lunarcore.game.inventory.GameItem;
|
|||||||
import emu.lunarcore.game.inventory.ItemMainType;
|
import emu.lunarcore.game.inventory.ItemMainType;
|
||||||
import emu.lunarcore.game.player.Player;
|
import emu.lunarcore.game.player.Player;
|
||||||
|
|
||||||
@Command(label = "clear")
|
@Command(label = "clear", permission = "player.clear")
|
||||||
public class ClearCommand implements CommandHandler {
|
public class ClearCommand implements CommandHandler {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import emu.lunarcore.game.player.Player;
|
|||||||
import emu.lunarcore.game.player.PlayerGender;
|
import emu.lunarcore.game.player.PlayerGender;
|
||||||
import emu.lunarcore.server.packet.send.PacketGetHeroBasicTypeInfoScRsp;
|
import emu.lunarcore.server.packet.send.PacketGetHeroBasicTypeInfoScRsp;
|
||||||
|
|
||||||
@Command(label = "gender")
|
@Command(label = "gender", permission = "player.gender")
|
||||||
public class GenderCommand implements CommandHandler {
|
public class GenderCommand implements CommandHandler {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import emu.lunarcore.game.inventory.ItemMainType;
|
|||||||
import emu.lunarcore.game.inventory.ItemSubType;
|
import emu.lunarcore.game.inventory.ItemSubType;
|
||||||
import emu.lunarcore.game.player.Player;
|
import emu.lunarcore.game.player.Player;
|
||||||
|
|
||||||
@Command(label = "giveall", aliases = {"ga"})
|
@Command(label = "giveall", aliases = {"ga"}, permission = "player.give")
|
||||||
public class GiveAllCommand implements CommandHandler {
|
public class GiveAllCommand implements CommandHandler {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import emu.lunarcore.game.inventory.GameItem;
|
|||||||
import emu.lunarcore.game.player.Player;
|
import emu.lunarcore.game.player.Player;
|
||||||
import emu.lunarcore.util.Utils;
|
import emu.lunarcore.util.Utils;
|
||||||
|
|
||||||
@Command(label = "give", aliases = {"g"})
|
@Command(label = "give", aliases = {"g"}, permission = "player.give")
|
||||||
public class GiveCommand implements CommandHandler {
|
public class GiveCommand implements CommandHandler {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -24,7 +24,7 @@ public class GiveCommand implements CommandHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int itemId = Utils.parseSafeInt(args.get(0));
|
int itemId = Utils.parseSafeInt(args.get(0));
|
||||||
int amount = Math.max(args.getCount(), 1);
|
int amount = Math.max(args.getAmount(), 1);
|
||||||
|
|
||||||
ItemExcel itemData = GameData.getItemExcelMap().get(itemId);
|
ItemExcel itemData = GameData.getItemExcelMap().get(itemId);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package emu.lunarcore.command.commands;
|
||||||
|
|
||||||
|
import emu.lunarcore.command.Command;
|
||||||
|
import emu.lunarcore.command.CommandArgs;
|
||||||
|
import emu.lunarcore.command.CommandHandler;
|
||||||
|
import emu.lunarcore.game.player.Player;
|
||||||
|
|
||||||
|
@Command(label = "permission", aliases = {"perm"}, permission = "server.permission")
|
||||||
|
public class PermissionCommand implements CommandHandler {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(Player sender, CommandArgs args) {
|
||||||
|
// Check target
|
||||||
|
if (args.getTarget() == null) {
|
||||||
|
this.sendMessage(sender, "Error: Targeted player not found or offline");
|
||||||
|
return;
|
||||||
|
} else if (args.size() < 2) {
|
||||||
|
this.sendMessage(sender, "Error: Not enough arguments");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String type = args.get(0).toLowerCase();
|
||||||
|
String permission = args.get(1).toLowerCase();
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case "add" -> {
|
||||||
|
// Add permission
|
||||||
|
args.getTarget().getAccount().addPermission(permission);
|
||||||
|
// Send message
|
||||||
|
this.sendMessage(sender, "Added permission for " + args.getTarget().getName());
|
||||||
|
}
|
||||||
|
case "remove" -> {
|
||||||
|
// Remove permission
|
||||||
|
args.getTarget().getAccount().removePermission(permission);
|
||||||
|
// Send message
|
||||||
|
this.sendMessage(sender, "Removed permission for " + args.getTarget().getName());
|
||||||
|
}
|
||||||
|
case "clear" -> {
|
||||||
|
// Clear permissions
|
||||||
|
args.getTarget().getAccount().clearPermission();
|
||||||
|
// Send message
|
||||||
|
this.sendMessage(sender, "Cleared permissions for " + args.getTarget().getName());
|
||||||
|
}
|
||||||
|
default -> {
|
||||||
|
this.sendMessage(sender, "Error: Invalid argument");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -6,7 +6,7 @@ import emu.lunarcore.command.CommandArgs;
|
|||||||
import emu.lunarcore.command.CommandHandler;
|
import emu.lunarcore.command.CommandHandler;
|
||||||
import emu.lunarcore.game.player.Player;
|
import emu.lunarcore.game.player.Player;
|
||||||
|
|
||||||
@Command(label = "reload")
|
@Command(label = "reload", permission = "server.reload")
|
||||||
public class ReloadCommand implements CommandHandler {
|
public class ReloadCommand implements CommandHandler {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import emu.lunarcore.game.scene.entity.EntityMonster;
|
|||||||
import emu.lunarcore.util.Position;
|
import emu.lunarcore.util.Position;
|
||||||
import emu.lunarcore.util.Utils;
|
import emu.lunarcore.util.Utils;
|
||||||
|
|
||||||
@Command(label = "spawn")
|
@Command(label = "spawn", permission = "player.spawn")
|
||||||
public class SpawnCommand implements CommandHandler {
|
public class SpawnCommand implements CommandHandler {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -32,7 +32,7 @@ public class SpawnCommand implements CommandHandler {
|
|||||||
// Get id
|
// Get id
|
||||||
int id = Utils.parseSafeInt(args.get(0));
|
int id = Utils.parseSafeInt(args.get(0));
|
||||||
int stage = Math.max(Utils.parseSafeInt(args.get(1)), 1);
|
int stage = Math.max(Utils.parseSafeInt(args.get(1)), 1);
|
||||||
int amount = Math.max(args.getCount(), 1);
|
int amount = Math.max(args.getAmount(), 1);
|
||||||
int radius = Math.max(args.getRank(), 5) * 1000;
|
int radius = Math.max(args.getRank(), 5) * 1000;
|
||||||
|
|
||||||
// Spawn monster
|
// Spawn monster
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import emu.lunarcore.command.CommandHandler;
|
|||||||
import emu.lunarcore.game.player.Player;
|
import emu.lunarcore.game.player.Player;
|
||||||
import emu.lunarcore.util.Utils;
|
import emu.lunarcore.util.Utils;
|
||||||
|
|
||||||
@Command(label = "worldlevel", aliases = {"wl"})
|
@Command(label = "worldlevel", aliases = {"wl"}, permission = "player.worldlevel")
|
||||||
public class WorldLevelCommand implements CommandHandler {
|
public class WorldLevelCommand implements CommandHandler {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
package emu.lunarcore.game.account;
|
package emu.lunarcore.game.account;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import dev.morphia.annotations.*;
|
import dev.morphia.annotations.*;
|
||||||
import emu.lunarcore.LunarRail;
|
import emu.lunarcore.LunarRail;
|
||||||
import emu.lunarcore.util.Crypto;
|
import emu.lunarcore.util.Crypto;
|
||||||
@@ -21,6 +24,8 @@ public class Account {
|
|||||||
|
|
||||||
private String comboToken; // Combo token
|
private String comboToken; // Combo token
|
||||||
private String dispatchToken; // Session token for dispatch server
|
private String dispatchToken; // Session token for dispatch server
|
||||||
|
|
||||||
|
private Set<String> permissions;
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public Account() {
|
public Account() {
|
||||||
@@ -30,6 +35,7 @@ public class Account {
|
|||||||
public Account(String username) {
|
public Account(String username) {
|
||||||
this.uid = Long.toString(Snowflake32.newUid());
|
this.uid = Long.toString(Snowflake32.newUid());
|
||||||
this.username = username;
|
this.username = username;
|
||||||
|
this.permissions = new HashSet<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getEmail() {
|
public String getEmail() {
|
||||||
@@ -39,20 +45,108 @@ public class Account {
|
|||||||
public void setReservedPlayerUid(int uid) {
|
public void setReservedPlayerUid(int uid) {
|
||||||
this.reservedPlayerUid = uid;
|
this.reservedPlayerUid = uid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Permissions
|
||||||
|
|
||||||
|
public Set<String> getPermissions() {
|
||||||
|
if (this.permissions == null) {
|
||||||
|
this.permissions = new HashSet<>();
|
||||||
|
this.save();
|
||||||
|
}
|
||||||
|
return this.permissions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean addPermission(String permission) {
|
||||||
|
if (this.getPermissions().contains(permission)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.getPermissions().add(permission);
|
||||||
|
this.save();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean permissionMatchesWildcard(String wildcard, String[] permissionParts) {
|
||||||
|
String[] wildcardParts = wildcard.split("\\.");
|
||||||
|
if (permissionParts.length < wildcardParts.length) { // A longer wildcard can never match a shorter permission
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < wildcardParts.length; i++) {
|
||||||
|
switch (wildcardParts[i]) {
|
||||||
|
case "**": // Recursing match
|
||||||
|
return true;
|
||||||
|
case "*": // Match only one layer
|
||||||
|
if (i >= (permissionParts.length-1)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default: // This layer isn't a wildcard, it needs to match exactly
|
||||||
|
if (!wildcardParts[i].equals(permissionParts[i])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// At this point the wildcard will have matched every layer, but if it is shorter then the permission then this is not a match at this point (no **).
|
||||||
|
return wildcardParts.length == permissionParts.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasPermission(String permission) {
|
||||||
|
// Skip if permission isnt required
|
||||||
|
if (permission.isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default permissions
|
||||||
|
var defaultPermissions = LunarRail.getConfig().getServerOptions().getDefaultPermissions();
|
||||||
|
|
||||||
|
if (defaultPermissions.contains("*")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add default permissions if it doesn't exist
|
||||||
|
List<String> permissions = Stream.of(this.getPermissions(), defaultPermissions)
|
||||||
|
.flatMap(Collection::stream)
|
||||||
|
.distinct().toList();
|
||||||
|
|
||||||
|
if (permissions.contains(permission)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] permissionParts = permission.split("\\.");
|
||||||
|
for (String p : permissions) {
|
||||||
|
if (p.startsWith("-") && permissionMatchesWildcard(p.substring(1), permissionParts)) return false;
|
||||||
|
if (permissionMatchesWildcard(p, permissionParts)) return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return permissions.contains("*");
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean removePermission(String permission) {
|
||||||
|
boolean res = this.getPermissions().remove(permission);
|
||||||
|
if (res) this.save();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearPermission() {
|
||||||
|
this.getPermissions().clear();
|
||||||
|
this.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tokens
|
||||||
|
|
||||||
// TODO make unique
|
|
||||||
public String generateComboToken() {
|
public String generateComboToken() {
|
||||||
this.comboToken = Utils.bytesToHex(Crypto.createSessionKey(32));
|
this.comboToken = Utils.bytesToHex(Crypto.createSessionKey(32)); // TODO make unique
|
||||||
this.save();
|
this.save();
|
||||||
return this.comboToken;
|
return this.comboToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO make unique
|
|
||||||
public String generateDispatchToken() {
|
public String generateDispatchToken() {
|
||||||
this.dispatchToken = Utils.bytesToHex(Crypto.createSessionKey(32));
|
this.dispatchToken = Utils.bytesToHex(Crypto.createSessionKey(32)); // TODO make unique
|
||||||
this.save();
|
this.save();
|
||||||
return this.dispatchToken;
|
return this.dispatchToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Database
|
||||||
|
|
||||||
public void save() {
|
public void save() {
|
||||||
LunarRail.getAccountDatabase().save(this);
|
LunarRail.getAccountDatabase().save(this);
|
||||||
|
|||||||
Reference in New Issue
Block a user