From 133b9917b424d79eb2a07e5cc9ff729f1a470896 Mon Sep 17 00:00:00 2001 From: Marc Baloup Date: Sat, 17 Apr 2021 00:06:21 +0200 Subject: [PATCH] Ability to list all effective permissions for a specific player or group --- .../lib/core/permissions/PermEntity.java | 14 ++++++ .../PermissionsCachedBackendReader.java | 2 +- .../core/permissions/PermissionsResolver.java | 49 ++++++++++++++++++- .../lib/core/permissions/ServerWorldKey.java | 7 +-- 4 files changed, 66 insertions(+), 6 deletions(-) diff --git a/Core/src/main/java/fr/pandacube/lib/core/permissions/PermEntity.java b/Core/src/main/java/fr/pandacube/lib/core/permissions/PermEntity.java index 2ebd099..ecfdae3 100644 --- a/Core/src/main/java/fr/pandacube/lib/core/permissions/PermEntity.java +++ b/Core/src/main/java/fr/pandacube/lib/core/permissions/PermEntity.java @@ -1,6 +1,7 @@ package fr.pandacube.lib.core.permissions; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Set; @@ -76,6 +77,19 @@ public abstract class PermEntity { } + public Map listEffectivePermissions() { + return Permissions.resolver.getEffectivePermissionList(name, type, null, null); + } + + public Map listEffectivePermissions(String server) { + return Permissions.resolver.getEffectivePermissionList(name, type, server, null); + } + + public Map listEffectivePermissions(String server, String world) { + return Permissions.resolver.getEffectivePermissionList(name, type, server, world); + } + + public Boolean hasPermission(String permission) { return Permissions.resolver.getEffectivePermission(name, type, permission, null, null); } diff --git a/Core/src/main/java/fr/pandacube/lib/core/permissions/PermissionsCachedBackendReader.java b/Core/src/main/java/fr/pandacube/lib/core/permissions/PermissionsCachedBackendReader.java index 2dc70d8..98c2400 100644 --- a/Core/src/main/java/fr/pandacube/lib/core/permissions/PermissionsCachedBackendReader.java +++ b/Core/src/main/java/fr/pandacube/lib/core/permissions/PermissionsCachedBackendReader.java @@ -89,7 +89,7 @@ import fr.pandacube.lib.core.util.Log; playerSelfPerms = playerRawData.get("permissions").stream() .peek(e -> { String value = e.get(SQLPermissions.value); - fullPermissionsList.add(value.substring(value.startsWith("-") ? 1 : 0)); + fullPermissionsList.add(value.substring(value.startsWith("-") ? 1 : 0).toLowerCase()); }) .collect(Collectors.groupingBy(e -> new ServerWorldKey(e.get(SQLPermissions.server), e.get(SQLPermissions.world)), LinkedHashMap::new, diff --git a/Core/src/main/java/fr/pandacube/lib/core/permissions/PermissionsResolver.java b/Core/src/main/java/fr/pandacube/lib/core/permissions/PermissionsResolver.java index 939822e..cdf2b91 100644 --- a/Core/src/main/java/fr/pandacube/lib/core/permissions/PermissionsResolver.java +++ b/Core/src/main/java/fr/pandacube/lib/core/permissions/PermissionsResolver.java @@ -2,7 +2,9 @@ package fr.pandacube.lib.core.permissions; import java.util.ArrayList; import java.util.EnumSet; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.UUID; @@ -39,6 +41,9 @@ public class PermissionsResolver { synchronized (effectivePermissionsCache) { effectivePermissionsCache.asMap().keySet().removeIf(k -> k.type == EntityType.User && playerId.equals(k.name)); } + synchronized (effectivePermissionsListCache) { + effectivePermissionsListCache.asMap().keySet().removeIf(k -> k.type == EntityType.User && playerId.equals(k.name)); + } synchronized (effectiveDataCache) { effectiveDataCache.asMap().keySet().removeIf(k -> k.type == EntityType.User && playerId.equals(k.name)); } @@ -46,6 +51,7 @@ public class PermissionsResolver { /* package */ void clearCache() { effectivePermissionsCache.invalidateAll(); + effectivePermissionsListCache.invalidateAll(); effectiveDataCache.invalidateAll(); } @@ -70,7 +76,7 @@ public class PermissionsResolver { } private Cache effectiveDataCache = CacheBuilder.newBuilder() - .expireAfterWrite(5, TimeUnit.MINUTES) + .expireAfterAccess(10, TimeUnit.MINUTES) .build(); private String getEffectiveData(String name, EntityType type, DataType dataType) { @@ -220,9 +226,48 @@ public class PermissionsResolver { + + + + + + + + + private Cache> effectivePermissionsListCache = CacheBuilder.newBuilder() + .expireAfterAccess(10, TimeUnit.MINUTES) + .build(); + + /* package */ Map getEffectivePermissionList(String name, EntityType type, String server, String world) { + Preconditions.checkNotNull(name, "name can’t be null"); + Preconditions.checkNotNull(type, "type can’t be null"); + Preconditions.checkArgument(world == null || server != null, "world not null but server is null"); + + String fServer = server == null ? null : server.toLowerCase(); + String fWorld = world == null ? null : world.toLowerCase(); + + try { + return effectivePermissionsListCache.get(new PermCacheKey(name, type, null, fServer, fWorld), () -> { + Map permList = new LinkedHashMap<>(); + + for (String perm : backendReader.getFullPermissionsList()) { + Boolean has = getEffectivePermission(name, type, perm, fServer, fWorld); + if (has == null) + continue; + permList.put(perm.toLowerCase(), has); + } + + return permList; + }); + } catch (ExecutionException e) { + Log.severe(e); + return null; + } + + } private Cache effectivePermissionsCache = CacheBuilder.newBuilder() - .expireAfterWrite(5, TimeUnit.MINUTES) + .expireAfterAccess(10, TimeUnit.MINUTES) .build(); /* package */ Boolean getEffectivePermission(String name, EntityType type, String permission, String server, String world) { diff --git a/Core/src/main/java/fr/pandacube/lib/core/permissions/ServerWorldKey.java b/Core/src/main/java/fr/pandacube/lib/core/permissions/ServerWorldKey.java index ecfb2de..3ebebd8 100644 --- a/Core/src/main/java/fr/pandacube/lib/core/permissions/ServerWorldKey.java +++ b/Core/src/main/java/fr/pandacube/lib/core/permissions/ServerWorldKey.java @@ -20,11 +20,12 @@ public class ServerWorldKey implements Comparable { public int hashCode() { return Objects.hash(world, server); } + + private static final Comparator STR_NULL_FIRST_COMPARATOR = Comparator.nullsFirst(String::compareToIgnoreCase); @Override public int compareTo(ServerWorldKey o) { - Comparator compStrNullFirst = Comparator.nullsFirst(String::compareToIgnoreCase); - return Comparator.comparing((ServerWorldKey k) -> k.server, compStrNullFirst) - .thenComparing(k -> k.world, compStrNullFirst) + return Comparator.comparing((ServerWorldKey k) -> k.server, STR_NULL_FIRST_COMPARATOR) + .thenComparing(k -> k.world, STR_NULL_FIRST_COMPARATOR) .compare(this, o); } } \ No newline at end of file