Skip to content

Commit 0d44d87

Browse files
TomGrobbesir-lord-pizza
authored andcommitted
fix(permissions): keep plugins, higher spawn limits and teleport managing to staff
1 parent f602ae0 commit 0d44d87

6 files changed

Lines changed: 24 additions & 10 deletions

File tree

src/Server/vMenu.Enhanced.Permissions.Server/PermissionNode.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ public sealed class PermissionNode
1313
// Only steers which principal the generated example suggests, never a live check.
1414
public bool IsStaffOnly { get; internal set; }
1515

16+
// Whether being staff only carries down to everything nested underneath.
17+
public bool CascadesStaffOnly { get; init; } = true;
18+
1619
public required IReadOnlyList<string> ExtraParents { get; init; }
1720

1821
public PermissionNode? StructuralParent { get; internal set; }

src/Server/vMenu.Enhanced.Permissions.Server/PermissionRegistry.cs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,14 @@ public static void Build(Assembly assembly)
3131
var discovered = Discover(assembly);
3232

3333
// Metadata order is stable per build but not contractual, so sort for a deterministic tree.
34-
foreach (var (name, extraParents, isStaffOnly) in discovered.OrderBy(entry => entry.Name, StringComparer.Ordinal))
34+
foreach (var (name, extraParents, isStaffOnly, cascades) in discovered.OrderBy(entry => entry.Name, StringComparer.Ordinal))
3535
{
3636
Nodes[name] = new PermissionNode
3737
{
3838
Name = name,
3939
ExtraParents = extraParents,
4040
IsStaffOnly = isStaffOnly,
41+
CascadesStaffOnly = cascades,
4142
};
4243
}
4344

@@ -74,7 +75,7 @@ public static bool RegisterDynamic(string permission, string source, bool staffO
7475
{
7576
Name = permission,
7677
Source = source,
77-
IsStaffOnly = parent.IsStaffOnly || staffOnly,
78+
IsStaffOnly = (parent.IsStaffOnly && parent.CascadesStaffOnly) || staffOnly,
7879
ExtraParents = parent.ExtraParents,
7980
StructuralParent = parent,
8081
};
@@ -204,9 +205,9 @@ private static Type[] TypesIn(Assembly assembly)
204205
}
205206
}
206207

207-
private static List<(string Name, string[] ExtraParents, bool IsStaffOnly)> Discover(Assembly assembly)
208+
private static List<(string Name, string[] ExtraParents, bool IsStaffOnly, bool Cascades)> Discover(Assembly assembly)
208209
{
209-
var discovered = new List<(string Name, string[] ExtraParents, bool IsStaffOnly)>();
210+
var discovered = new List<(string Name, string[] ExtraParents, bool IsStaffOnly, bool Cascades)>();
210211
var owners = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
211212

212213
foreach (var type in TypesIn(assembly))
@@ -219,7 +220,7 @@ private static Type[] TypesIn(Assembly assembly)
219220
}
220221

221222
var prefix = category.Prefix ?? DerivePrefix(type);
222-
var categoryIsStaffOnly = type.GetCustomAttribute<StaffOnlyAttribute>() is not null;
223+
var categoryStaffOnly = type.GetCustomAttribute<StaffOnlyAttribute>();
223224
var hasContainerGrant = false;
224225
var declaredInCategory = 0;
225226

@@ -258,8 +259,8 @@ private static Type[] TypesIn(Assembly assembly)
258259
hasContainerGrant |= PermissionPath.IsContainerGrant(value);
259260
declaredInCategory++;
260261

261-
var isStaffOnly = categoryIsStaffOnly || field.GetCustomAttribute<StaffOnlyAttribute>() is not null;
262-
discovered.Add((value, category.AdditionalParents, isStaffOnly));
262+
var staffOnly = field.GetCustomAttribute<StaffOnlyAttribute>() ?? categoryStaffOnly;
263+
discovered.Add((value, category.AdditionalParents, staffOnly is not null, staffOnly?.Cascades ?? true));
263264
}
264265

265266
// A single-permission category has nothing to group, so no container grant is expected. Neither does
@@ -321,7 +322,7 @@ static void MarkStaffOnlyBelow(PermissionNode node)
321322
{
322323
foreach (var child in node.StructuralChildren)
323324
{
324-
child.IsStaffOnly |= node.IsStaffOnly;
325+
child.IsStaffOnly |= node.IsStaffOnly && node.CascadesStaffOnly;
325326
MarkStaffOnlyBelow(child);
326327
}
327328
}

src/Shared/vMenu.Enhanced.Data/Permissions/Menus/TeleportMenu.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,6 @@ public static class TeleportMenu
1717
public const string Category = "vMenu.Enhanced.Menus.TeleportMenu.Category";
1818

1919
// Adding or removing a category or a location, which writes the config file for everybody.
20+
[StaffOnly]
2021
public const string Manage = "vMenu.Enhanced.Menus.TeleportMenu.Manage";
2122
}

src/Shared/vMenu.Enhanced.Data/Permissions/Menus/VehicleSpawner.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ public static class VehicleSpawner
1414

1515
public const string SpawnLimitTier1 = "vMenu.Enhanced.Menus.VehicleSpawner.SpawnLimitTier1";
1616

17+
[StaffOnly]
1718
public const string SpawnLimitTier2 = "vMenu.Enhanced.Menus.VehicleSpawner.SpawnLimitTier2";
1819

20+
[StaffOnly]
1921
public const string SpawnLimitTier3 = "vMenu.Enhanced.Menus.VehicleSpawner.SpawnLimitTier3";
2022
}

src/Shared/vMenu.Enhanced.Data/Permissions/Plugins.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ public static class Plugins
77
{
88
public const string Prefix = "vMenu.Enhanced.Plugins";
99

10-
// Grants every permission of every plugin.
10+
// Grants every permission of every plugin, including ones installed later, so it stays with staff.
11+
// Each plugin's own permissions keep whatever its author suggested.
12+
[StaffOnly(Cascades = false)]
1113
public const string All = Prefix + PermissionPath.AllSuffix;
1214

1315
public static string AllFor(string pluginId) =>

src/Shared/vMenu.Enhanced.Data/Permissions/StaffOnlyAttribute.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,9 @@ namespace vMenu.Enhanced.Data.Permissions;
44
// than to everybody. It only picks the principal written into permissions.cfg.example; nothing is
55
// enforced by it, since a server owner is free to edit their copy however they like.
66
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
7-
public sealed class StaffOnlyAttribute : Attribute;
7+
public sealed class StaffOnlyAttribute : Attribute
8+
{
9+
// A container that should stay with staff while what sits under it is still suggested to everybody
10+
// one line at a time, so granting the lot stays a deliberate choice without hiding the parts.
11+
public bool Cascades { get; init; } = true;
12+
}

0 commit comments

Comments
 (0)