Flan ignores global permissions
LukeOnuke opened this issue ยท 0 comments
Modloader
Fabric
Minecraft version
1.21.8
Modloader version
fabric-api 0.129.0+1.21.8
Mod version
flan-1.21.8-1.12.0-fabric / 1.21.8 branch
Description
What happens?
Flan disregards global permissions with all players, regardless of their permissions with the permission api or with their vanilla permission level (op status).
Why is this important?
This causes problems in servers such as my own and with others #413 where players can give themselves gamebreaking potion effects or edit the entrance/exit text (if for example the server doesn't want to allow it, like my own).
How does this happen?
In this section of the bug report ill give a in depth view about my findings in the source code as to why this happens, I'll shortly be committing a pull request that addresses this.
Preamble, config.
The default config has this in global permissions.
"globalDefaultPerms": {
"*": {
"flan:edit_potions": "ALLFALSE",
"flan:flight": "ALLTRUE",
"flan:lock_items": "ALLTRUE",
"flan:may_flight": "ALLFALSE",
"flan:mob_spawn": "ALLFALSE",
"flan:no_hunger": "ALLFALSE",
"flan:teleport": "ALLFALSE"
}
}Permission checking
I did some digging around as to how permissions are checked.
In the handler for the claim menu screen, this is the display that utilizes the same method:
This is the line that does it in the click handler, same class:
If we go into that method and inject logging code for debug.
private void logIfEditPoutions(ResourceLocation perm, String message){
if(perm.toString().equals("flan:edit_potions")) Flan.LOGGER.info("canInterract({}, ...): {}", perm.toString(), message);
}
@Override
public boolean canInteract(ServerPlayer player, ResourceLocation perm, BlockPos pos, boolean message) {
logIfEditPoutions(perm, "BEGIN");
boolean realPlayer = player != null && player.getClass().equals(ServerPlayer.class);
message = message && realPlayer && player.connection != null; //dont send messages to fake players
//Delegate interaction to FAKEPLAYER perm if a fake player
if (player != null && !realPlayer) {
//Some mods use the actual user/placer/owner whatever of the fakeplayer. E.g. ComputerCraft
//For those mods we dont pass them as fake players
if (this.fakePlayers.contains(player.getUUID()))
return true;
if (!player.getUUID().equals(this.owner) && !this.playersGroups.containsKey(player.getUUID())) {
perm = BuiltinPermission.FAKEPLAYER;
}
}
InteractionResult res = ClaimEvents.INSTANCE.claimCheck(player, perm, pos);
logIfEditPoutions(perm, "InteractionResult= " + res); //debug
if (res != InteractionResult.PASS)
return res != InteractionResult.FAIL;
if (!this.isAdminClaim()) {
Config.GlobalType global = ConfigHandler.CONFIG.getGlobal(this.level, perm);
logIfEditPoutions(perm, "global.getValue= " + global.getValue()); //debug
if (!global.canModify()) {
if (global.getValue() || (player != null && this.playerBypassesPermission(player, perm))){
logIfEditPoutions(perm, "return true ");
return true;
}
if (message)
player.displayClientMessage(ClaimUtils.translatedText("flan.noPermissionSimple", ChatFormatting.DARK_RED), true);
if (perm.equals(BuiltinPermission.FAKEPLAYER))
this.getOwnerPlayer().ifPresent(p -> PlayerClaimData.get(p).notifyFakePlayerInteraction(player, pos, this));
logIfEditPoutions(perm, "return false "); //debug
return false;
}
logIfEditPoutions(perm, "PASSED " + global.getValue()); //debug
if (ConfigHandler.CONFIG.offlineProtectActivation != -1 && (LogoutTracker.getInstance(this.level.getServer()).justLoggedOut(this.getOwner()) || this.getOwnerPlayer().isPresent())) {
return global == Config.GlobalType.NONE || global.getValue();
}
}
if (PermissionManager.getInstance().isGlobalPermission(perm)) {
for (Claim claim : this.subClaims) {
if (claim.insideClaim(pos)) {
return claim.canInteract(player, perm, pos, message);
}
}
if (this.hasPerm(perm))
return true;
if (message)
player.displayClientMessage(ClaimUtils.translatedText("flan.noPermissionSimple", ChatFormatting.DARK_RED), true);
if (perm.equals(BuiltinPermission.FAKEPLAYER))
this.getOwnerPlayer().ifPresent(p -> PlayerClaimData.get(p).notifyFakePlayerInteraction(player, pos, this));
return false;
}
if (this.playerBypassesPermission(player, perm))
return true;
if (!perm.equals(BuiltinPermission.EDITCLAIM) && !perm.equals(BuiltinPermission.EDITPERMS))
for (Claim claim : this.subClaims) {
if (claim.insideClaim(pos)) {
return claim.canInteract(player, perm, pos, message);
}
}
if (this.playersGroups.containsKey(player.getUUID())) {
Map<ResourceLocation, Boolean> map = this.permissions.get(this.playersGroups.get(player.getUUID()));
if (map != null && map.containsKey(perm)) {
if (map.get(perm))
return true;
if (message)
player.displayClientMessage(ClaimUtils.translatedText("flan.noPermissionSimple", ChatFormatting.DARK_RED), true);
if (perm.equals(BuiltinPermission.FAKEPLAYER))
this.getOwnerPlayer().ifPresent(p -> PlayerClaimData.get(p).notifyFakePlayerInteraction(player, pos, this));
return false;
}
}
if (this.hasPerm(perm))
return true;
if (message)
player.displayClientMessage(ClaimUtils.translatedText("flan.noPermissionSimple", ChatFormatting.DARK_RED), true);
if (perm.equals(BuiltinPermission.FAKEPLAYER))
this.getOwnerPlayer().ifPresent(p -> PlayerClaimData.get(p).notifyFakePlayerInteraction(player, pos, this));
return false;
}You will notice that at the end it returns true at:
Flan/common/src/main/java/io/github/flemmli97/flan/claim/Claim.java
Lines 326 to 327 in b847939
This is according to the log you get in console thanks to the added loggers:
[16:21:43] [Server thread/INFO] (flan) canInterract(flan:edit_potions, ...): BEGIN
[16:21:43] [Server thread/INFO] (flan) canInterract(flan:edit_potions, ...): InteractionResult= Pass[]
[16:21:43] [Server thread/INFO] (flan) canInterract(flan:edit_potions, ...): global.getValue= false
[16:21:43] [Server thread/INFO] (flan) canInterract(flan:edit_potions, ...): return true According to that if statement and the situation where these checks are called it can be presumed that:
- the permission will be false (actually checked this with the inserted logger, refer to code block above)
- player will not be null
this.playerBypassesPermission(player, perm))has to return true in order for thereturn trueto be called
The aforementioned method doesnt check for global permissions, it will just return true if its the owner of the claim.
Flan/common/src/main/java/io/github/flemmli97/flan/claim/Claim.java
Lines 387 to 388 in b847939
Steps to reproduce
- Load up a blank server with flan, with default configs.
- Join the game as non op.
- Click on edit potion effects.
- Watch as flan disregards global permissions.
Mods that might affect the issue
N/A
Logs
https://gist.github.com/LukeOnuke/fe87328c0827309c35188d5b9aa1d9bf