diff --git a/Content.Client/Administration/ClientAdminManager.cs b/Content.Client/Administration/ClientAdminManager.cs
index 96b644579c..4301bfe8d0 100644
--- a/Content.Client/Administration/ClientAdminManager.cs
+++ b/Content.Client/Administration/ClientAdminManager.cs
@@ -21,8 +21,6 @@ namespace Content.Client.Administration
public event Action? AdminStatusUpdated;
- public AdminFlags? Flags => _adminData?.Flags;
-
public bool HasFlag(AdminFlags flag)
{
return _adminData?.HasFlag(flag) ?? false;
@@ -67,12 +65,12 @@ namespace Content.Client.Administration
_adminData = message.Admin;
if (_adminData != null)
{
- var flagsText = string.Join("|", AdminFlagsExt.FlagsToNames(_adminData.Flags));
+ var flagsText = string.Join("|", AdminFlagsHelper.FlagsToNames(_adminData.Flags));
Logger.InfoS("admin", $"Updated admin status: {_adminData.Active}/{_adminData.Title}/{flagsText}");
}
else
{
- Logger.InfoS("admin", $"Updated admin status: Not admin");
+ Logger.InfoS("admin", "Updated admin status: Not admin");
}
AdminStatusUpdated?.Invoke();
diff --git a/Content.Client/Administration/IClientAdminManager.cs b/Content.Client/Administration/IClientAdminManager.cs
index 1bdf0cb029..e675e3f378 100644
--- a/Content.Client/Administration/IClientAdminManager.cs
+++ b/Content.Client/Administration/IClientAdminManager.cs
@@ -1,19 +1,50 @@
using System;
using Content.Shared.Administration;
+#nullable enable
+
namespace Content.Client.Administration
{
+ ///
+ /// Manages server admin permissions for the local player.
+ ///
public interface IClientAdminManager
{
- public event Action AdminStatusUpdated;
+ ///
+ /// Fired when the admin status of the local player changes, such as losing admin privileges.
+ ///
+ event Action AdminStatusUpdated;
- AdminFlags? Flags { get; }
+ ///
+ /// Checks whether the local player has an admin flag.
+ ///
+ /// The flags to check. Multiple flags can be specified, they must all be held.
+ /// False if the local player is not an admin, inactive, or does not have all the flags specified.
bool HasFlag(AdminFlags flag);
+ ///
+ /// Check if a player can execute a specified console command.
+ ///
bool CanCommand(string cmdName);
+
+ ///
+ /// Check if the local player can open the VV menu.
+ ///
bool CanViewVar();
+
+ ///
+ /// Check if the local player can spawn stuff in with the entity/tile spawn panel.
+ ///
bool CanAdminPlace();
+
+ ///
+ /// Check if the local player can execute server-side C# scripts.
+ ///
bool CanScript();
+
+ ///
+ /// Check if the local player can open the admin menu.
+ ///
bool CanAdminMenu();
void Initialize();
diff --git a/Content.Client/Chat/ChatBox.cs b/Content.Client/Chat/ChatBox.cs
index 627956a7d4..75e65ff87f 100644
--- a/Content.Client/Chat/ChatBox.cs
+++ b/Content.Client/Chat/ChatBox.cs
@@ -106,15 +106,12 @@ namespace Content.Client.Chat
AllButton.OnToggled += OnFilterToggled;
LocalButton.OnToggled += OnFilterToggled;
OOCButton.OnToggled += OnFilterToggled;
+ AdminButton.OnToggled += OnFilterToggled;
hBox.AddChild(AllButton);
hBox.AddChild(LocalButton);
hBox.AddChild(OOCButton);
- if(AdminButton != null)
- {
- AdminButton.OnToggled += OnFilterToggled;
- hBox.AddChild(AdminButton);
- }
+ hBox.AddChild(AdminButton);
AddChild(outerVBox);
}
diff --git a/Content.Client/UserInterface/Permissions/PermissionsEui.cs b/Content.Client/UserInterface/Permissions/PermissionsEui.cs
index 4801472f3e..6751962dc7 100644
--- a/Content.Client/UserInterface/Permissions/PermissionsEui.cs
+++ b/Content.Client/UserInterface/Permissions/PermissionsEui.cs
@@ -241,7 +241,7 @@ namespace Content.Client.UserInterface.Permissions
al.AddChild(rankControl);
- var flagsText = AdminFlagsExt.PosNegFlagsText(admin.PosFlags, admin.NegFlags);
+ var flagsText = AdminFlagsHelper.PosNegFlagsText(admin.PosFlags, admin.NegFlags);
al.AddChild(new Label
{
@@ -264,7 +264,7 @@ namespace Content.Client.UserInterface.Permissions
foreach (var kv in s.AdminRanks)
{
var rank = kv.Value;
- var flagsText = string.Join(' ', AdminFlagsExt.FlagsToNames(rank.Flags).Select(f => $"+{f}"));
+ var flagsText = string.Join(' ', AdminFlagsHelper.FlagsToNames(rank.Flags).Select(f => $"+{f}"));
_menu.AdminRanksList.AddChild(new Label {Text = rank.Name});
_menu.AdminRanksList.AddChild(new Label
{
@@ -390,7 +390,7 @@ namespace Content.Client.UserInterface.Permissions
VSeparationOverride = 0
};
- foreach (var flag in AdminFlagsExt.AllFlags)
+ foreach (var flag in AdminFlagsHelper.AllFlags)
{
// Can only grant out perms you also have yourself.
// Primarily intended to prevent people giving themselves +HOST with +PERMISSIONS but generalized.
@@ -527,7 +527,7 @@ namespace Content.Client.UserInterface.Permissions
NameEdit = new LineEdit
{
- PlaceHolder = "Rank name",
+ PlaceHolder = Loc.GetString("Rank name"),
};
if (data != null)
@@ -538,7 +538,7 @@ namespace Content.Client.UserInterface.Permissions
SaveButton = new Button {Text = Loc.GetString("Save"), SizeFlagsHorizontal = SizeFlags.ShrinkEnd | SizeFlags.Expand};
var flagsBox = new VBoxContainer();
- foreach (var flag in AdminFlagsExt.AllFlags)
+ foreach (var flag in AdminFlagsHelper.AllFlags)
{
// Can only grant out perms you also have yourself.
// Primarily intended to prevent people giving themselves +HOST with +PERMISSIONS but generalized.
diff --git a/Content.Server/Administration/AdminManager.cs b/Content.Server/Administration/AdminManager.cs
index 8048346941..4c1b9fc4d5 100644
--- a/Content.Server/Administration/AdminManager.cs
+++ b/Content.Server/Administration/AdminManager.cs
@@ -95,7 +95,7 @@ namespace Content.Server.Administration
_chat.DispatchServerMessage(session, Loc.GetString("You are now an admin."));
var plyData = session.ContentData()!;
- plyData.ExplicitlyDeadminned = true;
+ plyData.ExplicitlyDeadminned = false;
reg.Data.Active = true;
_chat.SendAdminAnnouncement(Loc.GetString("{0} re-adminned themselves.", session.Name));
@@ -203,7 +203,7 @@ namespace Content.Server.Administration
if (map.TryGetNode("Flags", out var flagsNode))
{
var flagNames = flagsNode.AsString().Split(",", StringSplitOptions.RemoveEmptyEntries);
- var flags = AdminFlagsExt.NamesToFlags(flagNames);
+ var flags = AdminFlagsHelper.NamesToFlags(flagNames);
foreach (var cmd in commands)
{
if (!_adminCommands.TryGetValue(cmd, out var exFlags))
@@ -316,7 +316,7 @@ namespace Content.Server.Administration
var data = new AdminData
{
Title = Loc.GetString("Host"),
- Flags = AdminFlagsExt.Everything,
+ Flags = AdminFlagsHelper.Everything,
};
return (data, null, true);
@@ -335,12 +335,12 @@ namespace Content.Server.Administration
if (dbData.AdminRank != null)
{
- flags = AdminFlagsExt.NamesToFlags(dbData.AdminRank.Flags.Select(p => p.Flag));
+ flags = AdminFlagsHelper.NamesToFlags(dbData.AdminRank.Flags.Select(p => p.Flag));
}
foreach (var dbFlag in dbData.Flags)
{
- var flag = AdminFlagsExt.NameToFlag(dbFlag.Flag);
+ var flag = AdminFlagsHelper.NameToFlag(dbFlag.Flag);
if (dbFlag.Negative)
{
flags &= ~flag;
diff --git a/Content.Server/Administration/Commands/DeAdminCommand.cs b/Content.Server/Administration/Commands/DeAdminCommand.cs
index 44135a0c1b..81a61194cf 100644
--- a/Content.Server/Administration/Commands/DeAdminCommand.cs
+++ b/Content.Server/Administration/Commands/DeAdminCommand.cs
@@ -6,7 +6,7 @@ using Robust.Shared.IoC;
#nullable enable
-namespace Content.Server.Administration
+namespace Content.Server.Administration.Commands
{
[UsedImplicitly]
[AdminCommand(AdminFlags.None)]
diff --git a/Content.Server/Administration/Commands/ReAdminCommand.cs b/Content.Server/Administration/Commands/ReAdminCommand.cs
index edd197b71f..8f78442689 100644
--- a/Content.Server/Administration/Commands/ReAdminCommand.cs
+++ b/Content.Server/Administration/Commands/ReAdminCommand.cs
@@ -4,7 +4,7 @@ using Robust.Shared.IoC;
#nullable enable
-namespace Content.Server.Administration
+namespace Content.Server.Administration.Commands
{
[AnyCommand]
public class ReAdminCommand : IClientCommand
diff --git a/Content.Server/Administration/PermissionsEui.cs b/Content.Server/Administration/PermissionsEui.cs
index 018b3a83ab..2c5ba53b08 100644
--- a/Content.Server/Administration/PermissionsEui.cs
+++ b/Content.Server/Administration/PermissionsEui.cs
@@ -39,17 +39,17 @@ namespace Content.Server.Administration
StateDirty();
LoadFromDb();
- _adminManager.OnPermsChanged += AdminManagerOnOnPermsChanged;
+ _adminManager.OnPermsChanged += AdminManagerOnPermsChanged;
}
public override void Closed()
{
base.Closed();
- _adminManager.OnPermsChanged -= AdminManagerOnOnPermsChanged;
+ _adminManager.OnPermsChanged -= AdminManagerOnPermsChanged;
}
- private void AdminManagerOnOnPermsChanged(AdminPermsChangedEventArgs obj)
+ private void AdminManagerOnPermsChanged(AdminPermsChangedEventArgs obj)
{
// Close UI if user loses +PERMISSIONS.
if (obj.Player == Player && !UserAdminFlagCheck(AdminFlags.Permissions))
@@ -72,8 +72,8 @@ namespace Content.Server.Administration
{
Admins = _admins.Select(p => new PermissionsEuiState.AdminData
{
- PosFlags = AdminFlagsExt.NamesToFlags(p.a.Flags.Where(f => !f.Negative).Select(f => f.Flag)),
- NegFlags = AdminFlagsExt.NamesToFlags(p.a.Flags.Where(f => f.Negative).Select(f => f.Flag)),
+ PosFlags = AdminFlagsHelper.NamesToFlags(p.a.Flags.Where(f => !f.Negative).Select(f => f.Flag)),
+ NegFlags = AdminFlagsHelper.NamesToFlags(p.a.Flags.Where(f => f.Negative).Select(f => f.Flag)),
Title = p.a.Title,
RankId = p.a.AdminRankId,
UserId = new NetUserId(p.a.UserId),
@@ -82,7 +82,7 @@ namespace Content.Server.Administration
AdminRanks = _adminRanks.ToDictionary(a => a.Id, a => new PermissionsEuiState.AdminRankData
{
- Flags = AdminFlagsExt.NamesToFlags(a.Flags.Select(p => p.Flag)),
+ Flags = AdminFlagsHelper.NamesToFlags(a.Flags.Select(p => p.Flag)),
Name = a.Name
})
};
@@ -185,7 +185,7 @@ namespace Content.Server.Administration
await _db.UpdateAdminRankAsync(rank);
- var flagText = string.Join(' ', AdminFlagsExt.FlagsToNames(ur.Flags).Select(f => $"+{f}"));
+ var flagText = string.Join(' ', AdminFlagsHelper.FlagsToNames(ur.Flags).Select(f => $"+{f}"));
Logger.InfoS("admin.perms", $"{Player} updated admin rank {rank.Name}/{flagText}.");
_adminManager.ReloadAdminsWithRank(ur.Id);
@@ -207,7 +207,7 @@ namespace Content.Server.Administration
await _db.AddAdminRankAsync(rank);
- var flagText = string.Join(' ', AdminFlagsExt.FlagsToNames(ar.Flags).Select(f => $"+{f}"));
+ var flagText = string.Join(' ', AdminFlagsHelper.FlagsToNames(ar.Flags).Select(f => $"+{f}"));
Logger.InfoS("admin.perms", $"{Player} added admin rank {rank.Name}/{flagText}.");
}
@@ -272,7 +272,7 @@ namespace Content.Server.Administration
var name = playerRecord?.LastSeenUserName ?? ua.UserId.ToString();
var title = ua.Title ?? "";
- var flags = AdminFlagsExt.PosNegFlagsText(ua.PosFlags, ua.NegFlags);
+ var flags = AdminFlagsHelper.PosNegFlagsText(ua.PosFlags, ua.NegFlags);
Logger.InfoS("admin.perms", $"{Player} updated admin {name} to {title}/{rankName}/{flags}");
@@ -347,7 +347,7 @@ namespace Content.Server.Administration
await _db.AddAdminAsync(admin);
var title = ca.Title ?? "";
- var flags = AdminFlagsExt.PosNegFlagsText(ca.PosFlags, ca.NegFlags);
+ var flags = AdminFlagsHelper.PosNegFlagsText(ca.PosFlags, ca.NegFlags);
Logger.InfoS("admin.perms", $"{Player} added admin {name} as {title}/{rankName}/{flags}");
@@ -392,7 +392,7 @@ namespace Content.Server.Administration
ret = rank.Name;
- var rankFlags = AdminFlagsExt.NamesToFlags(rank.Flags.Select(p => p.Flag));
+ var rankFlags = AdminFlagsHelper.NamesToFlags(rank.Flags.Select(p => p.Flag));
if (!UserAdminFlagCheck(rankFlags))
{
// Can't assign a rank with flags you don't have yourself.
@@ -421,8 +421,8 @@ namespace Content.Server.Administration
private static List GenAdminFlagList(AdminFlags posFlags, AdminFlags negFlags)
{
- var posFlagList = AdminFlagsExt.FlagsToNames(posFlags);
- var negFlagList = AdminFlagsExt.FlagsToNames(negFlags);
+ var posFlagList = AdminFlagsHelper.FlagsToNames(posFlags);
+ var negFlagList = AdminFlagsHelper.FlagsToNames(negFlags);
return posFlagList
.Select(f => new AdminFlag {Negative = false, Flag = f})
@@ -432,7 +432,7 @@ namespace Content.Server.Administration
private static List GenRankFlagList(AdminFlags flags)
{
- return AdminFlagsExt.FlagsToNames(flags).Select(f => new AdminRankFlag {Flag = f}).ToList();
+ return AdminFlagsHelper.FlagsToNames(flags).Select(f => new AdminRankFlag {Flag = f}).ToList();
}
private bool UserAdminFlagCheck(AdminFlags flags)
@@ -442,8 +442,8 @@ namespace Content.Server.Administration
private bool CanTouchAdmin(Admin admin)
{
- var posFlags = AdminFlagsExt.NamesToFlags(admin.Flags.Where(f => !f.Negative).Select(f => f.Flag));
- var rankFlags = AdminFlagsExt.NamesToFlags(
+ var posFlags = AdminFlagsHelper.NamesToFlags(admin.Flags.Where(f => !f.Negative).Select(f => f.Flag));
+ var rankFlags = AdminFlagsHelper.NamesToFlags(
admin.AdminRank?.Flags.Select(f => f.Flag) ?? Array.Empty());
var totalFlags = posFlags | rankFlags;
@@ -452,7 +452,7 @@ namespace Content.Server.Administration
private bool CanTouchRank(DbAdminRank rank)
{
- var rankFlags = AdminFlagsExt.NamesToFlags(rank.Flags.Select(f => f.Flag));
+ var rankFlags = AdminFlagsHelper.NamesToFlags(rank.Flags.Select(f => f.Flag));
return UserAdminFlagCheck(rankFlags);
}
diff --git a/Content.Server/Chat/ChatManager.cs b/Content.Server/Chat/ChatManager.cs
index 1d35847a94..afeb0c11b2 100644
--- a/Content.Server/Chat/ChatManager.cs
+++ b/Content.Server/Chat/ChatManager.cs
@@ -214,7 +214,6 @@ namespace Content.Server.Chat
var clients = _playerManager
.GetPlayersBy(x => x.AttachedEntity != null && x.AttachedEntity.HasComponent())
.Select(p => p.ConnectedClient);
- ;
var msg = _netManager.CreateNetMessage();
msg.Channel = ChatChannel.Dead;
diff --git a/Content.Shared/Administration/AdminData.cs b/Content.Shared/Administration/AdminData.cs
index 70ff7c6876..8c56f901ed 100644
--- a/Content.Shared/Administration/AdminData.cs
+++ b/Content.Shared/Administration/AdminData.cs
@@ -2,35 +2,64 @@
namespace Content.Shared.Administration
{
+ ///
+ /// Represents data for a single server admin.
+ ///
public sealed class AdminData
{
- public const string DefaultTitle = "Admin";
-
// Can be false if they're de-adminned with the ability to re-admin.
+ ///
+ /// Whether the admin is currently active. This can be false if they have de-adminned mid-round.
+ ///
public bool Active;
+
+ ///
+ /// The admin's title.
+ ///
public string? Title;
+
+ ///
+ /// The admin's permission flags.
+ ///
public AdminFlags Flags;
+ ///
+ /// Checks whether this admin has an admin flag.
+ ///
+ /// The flags to check. Multiple flags can be specified, they must all be held.
+ /// False if this admin is not or does not have all the flags specified.
public bool HasFlag(AdminFlags flag)
{
return Active && (Flags & flag) == flag;
}
+ ///
+ /// Check if this admin can open the VV menu.
+ ///
public bool CanViewVar()
{
return HasFlag(AdminFlags.VarEdit);
}
+ ///
+ /// Check if this admin can spawn stuff in with the entity/tile spawn panel.
+ ///
public bool CanAdminPlace()
{
return HasFlag(AdminFlags.Spawn);
}
+ ///
+ /// Check if this admin can execute server-side C# scripts.
+ ///
public bool CanScript()
{
return HasFlag(AdminFlags.Host);
}
+ ///
+ /// Check if this admin can open the admin menu.
+ ///
public bool CanAdminMenu()
{
return HasFlag(AdminFlags.Admin);
diff --git a/Content.Shared/Administration/AdminFlagsExt.cs b/Content.Shared/Administration/AdminFlagsHelper.cs
similarity index 63%
rename from Content.Shared/Administration/AdminFlagsExt.cs
rename to Content.Shared/Administration/AdminFlagsHelper.cs
index 0c018e8c3a..9d5bba3baa 100644
--- a/Content.Shared/Administration/AdminFlagsExt.cs
+++ b/Content.Shared/Administration/AdminFlagsHelper.cs
@@ -5,16 +5,28 @@ using System.Numerics;
namespace Content.Shared.Administration
{
- public static class AdminFlagsExt
+ ///
+ /// Contains various helper methods for working with admin flags.
+ ///
+ public static class AdminFlagsHelper
{
+ // As you can tell from the boatload of bitwise ops,
+ // writing this class was genuinely fun.
+
private static readonly Dictionary NameFlagsMap = new Dictionary();
private static readonly string[] FlagsNameMap = new string[32];
+ ///
+ /// Every admin flag in the game, at once!
+ ///
public static readonly AdminFlags Everything;
+ ///
+ /// A list of all individual admin flags.
+ ///
public static readonly IReadOnlyList AllFlags;
- static AdminFlagsExt()
+ static AdminFlagsHelper()
{
var t = typeof(AdminFlags);
var flags = (AdminFlags[]) Enum.GetValues(t);
@@ -24,6 +36,8 @@ namespace Content.Shared.Administration
{
var name = value.ToString().ToUpper();
+ // If, in the future, somebody adds a combined admin flag or something for convenience,
+ // ignore it.
if (BitOperations.PopCount((uint) value) != 1)
{
continue;
@@ -38,6 +52,15 @@ namespace Content.Shared.Administration
AllFlags = allFlags.ToArray();
}
+ ///
+ /// Converts an enumerable of admin flag names to a bitfield.
+ ///
+ ///
+ /// The flags must all be uppercase.
+ ///
+ ///
+ /// Thrown if a string that is not a valid admin flag is contained in .
+ ///
public static AdminFlags NamesToFlags(IEnumerable names)
{
var flags = AdminFlags.None;
@@ -54,11 +77,23 @@ namespace Content.Shared.Administration
return flags;
}
+ ///
+ /// Gets the flag bit for an admin flag name.
+ ///
+ ///
+ /// The flag name must be all uppercase.
+ ///
+ ///
+ /// Thrown if is not a valid admin flag name.
+ ///
public static AdminFlags NameToFlag(string name)
{
return NameFlagsMap[name];
}
+ ///
+ /// Converts a bitfield of admin flags to an array of all the flag names set.
+ ///
public static string[] FlagsToNames(AdminFlags flags)
{
var array = new string[BitOperations.PopCount((uint) flags)];
diff --git a/Content.Tests/Shared/Administration/AdminFlagsExtTest.cs b/Content.Tests/Shared/Administration/AdminFlagsExtTest.cs
index e44a8a1719..e2bc95a8f7 100644
--- a/Content.Tests/Shared/Administration/AdminFlagsExtTest.cs
+++ b/Content.Tests/Shared/Administration/AdminFlagsExtTest.cs
@@ -17,7 +17,7 @@ namespace Content.Tests.Shared.Administration
{
var names = namesConcat.Split(",", StringSplitOptions.RemoveEmptyEntries);
- Assert.That(AdminFlagsExt.NamesToFlags(names), Is.EqualTo(flags));
+ Assert.That(AdminFlagsHelper.NamesToFlags(names), Is.EqualTo(flags));
}
[Test]
@@ -29,7 +29,7 @@ namespace Content.Tests.Shared.Administration
{
var names = namesConcat.Split(",", StringSplitOptions.RemoveEmptyEntries);
- Assert.That(AdminFlagsExt.FlagsToNames(flags), Is.EquivalentTo(names));
+ Assert.That(AdminFlagsHelper.FlagsToNames(flags), Is.EquivalentTo(names));
}
}
}