// this is a sussy way to do this
foreach (var access in job.Access)
{
- if (_accessButtons.TryGetValue(access, out var button))
+ if (_accessButtons.TryGetValue(access, out var button) && !button.Disabled)
{
button.Pressed = true;
}
foreach (var access in groupPrototype.Tags)
{
- if (_accessButtons.TryGetValue(access, out var button))
+ if (_accessButtons.TryGetValue(access, out var button) && !button.Disabled)
{
button.Pressed = true;
}
if (interfaceEnabled)
{
button.Pressed = state.TargetIdAccessList?.Contains(accessName) ?? false;
+ button.Disabled = (!state.AllowedModifyAccessList?.Contains(accessName)) ?? true;
}
}
if (!component.Initialized)
return;
+ var privilegedIdName = string.Empty;
+ string[]? possibleAccess = null;
+ if (component.PrivilegedIdSlot.Item is { Valid: true } item)
+ {
+ privilegedIdName = EntityManager.GetComponent<MetaDataComponent>(item).EntityName;
+ possibleAccess = _accessReader.FindAccessTags(item).ToArray();
+ }
+
IdCardConsoleBoundUserInterfaceState newState;
// this could be prettier
if (component.TargetIdSlot.Item is not { Valid: true } targetId)
{
- var privilegedIdName = string.Empty;
- if (component.PrivilegedIdSlot.Item is { Valid: true } item)
- {
- privilegedIdName = EntityManager.GetComponent<MetaDataComponent>(item).EntityName;
- }
-
newState = new IdCardConsoleBoundUserInterfaceState(
component.PrivilegedIdSlot.HasItem,
PrivilegedIdIsAuthorized(uid, component),
null,
null,
null,
+ possibleAccess,
string.Empty,
privilegedIdName,
string.Empty);
{
var targetIdComponent = EntityManager.GetComponent<IdCardComponent>(targetId);
var targetAccessComponent = EntityManager.GetComponent<AccessComponent>(targetId);
- var name = string.Empty;
- if (component.PrivilegedIdSlot.Item is { Valid: true } item)
- name = EntityManager.GetComponent<MetaDataComponent>(item).EntityName;
var jobProto = string.Empty;
if (_station.GetOwningStation(uid) is { } station
targetIdComponent.FullName,
targetIdComponent.JobTitle,
targetAccessComponent.Tags.ToArray(),
+ possibleAccess,
jobProto,
- name,
+ privilegedIdName,
EntityManager.GetComponent<MetaDataComponent>(targetId).EntityName);
}
if (!newAccessList.TrueForAll(x => component.AccessLevels.Contains(x)))
{
- Logger.Warning("Tried to write unknown access tag.");
+ _sawmill.Warning($"User {ToPrettyString(uid)} tried to write unknown access tag.");
return;
}
var oldTags = _access.TryGetTags(targetId) ?? new List<string>();
oldTags = oldTags.ToList();
+ var privilegedId = component.PrivilegedIdSlot.Item;
+
if (oldTags.SequenceEqual(newAccessList))
return;
+ // I hate that C# doesn't have an option for this and don't desire to write this out the hard way.
+ // var difference = newAccessList.Difference(oldTags);
+ var difference = (newAccessList.Union(oldTags)).Except(newAccessList.Intersect(oldTags)).ToHashSet();
+ // NULL SAFETY: PrivilegedIdIsAuthorized checked this earlier.
+ var privilegedPerms = _accessReader.FindAccessTags(privilegedId!.Value).ToHashSet();
+ if (!difference.IsSubsetOf(privilegedPerms))
+ {
+ _sawmill.Warning($"User {ToPrettyString(uid)} tried to modify permissions they could not give/take!");
+ return;
+ }
+
var addedTags = newAccessList.Except(oldTags).Select(tag => "+" + tag).ToList();
var removedTags = oldTags.Except(newAccessList).Select(tag => "-" + tag).ToList();
_access.TrySetTags(targetId, newAccessList);
/// <summary>
/// Returns true if there is an ID in <see cref="IdCardConsoleComponent.PrivilegedIdSlot"/> and said ID satisfies the requirements of <see cref="AccessReaderComponent"/>.
/// </summary>
+ /// <remarks>
+ /// Other code relies on the fact this returns false if privileged Id is null. Don't break that invariant.
+ /// </remarks>
private bool PrivilegedIdIsAuthorized(EntityUid uid, IdCardConsoleComponent? component = null)
{
if (!Resolve(uid, ref component))
public readonly string? TargetIdFullName;
public readonly string? TargetIdJobTitle;
public readonly string[]? TargetIdAccessList;
+ public readonly string[]? AllowedModifyAccessList;
public readonly string TargetIdJobPrototype;
public IdCardConsoleBoundUserInterfaceState(bool isPrivilegedIdPresent,
string? targetIdFullName,
string? targetIdJobTitle,
string[]? targetIdAccessList,
+ string[]? allowedModifyAccessList,
string targetIdJobPrototype,
string privilegedIdName,
string targetIdName)
TargetIdFullName = targetIdFullName;
TargetIdJobTitle = targetIdJobTitle;
TargetIdAccessList = targetIdAccessList;
+ AllowedModifyAccessList = allowedModifyAccessList;
TargetIdJobPrototype = targetIdJobPrototype;
PrivilegedIdName = privilegedIdName;
TargetIdName = targetIdName;