diff --git a/Content.Server/Access/Components/IdCardConsoleComponent.cs b/Content.Server/Access/Components/IdCardConsoleComponent.cs index e4e034598a..a93e09e862 100644 --- a/Content.Server/Access/Components/IdCardConsoleComponent.cs +++ b/Content.Server/Access/Components/IdCardConsoleComponent.cs @@ -1,200 +1,11 @@ -using System.Linq; using Content.Server.Access.Systems; -using Content.Server.Station.Systems; -using Content.Server.StationRecords; -using Content.Server.UserInterface; using Content.Shared.Access.Components; -using Content.Shared.Access.Systems; -using Content.Shared.StationRecords; -using Content.Server.Administration.Logs; -using Content.Shared.Database; -using Content.Shared.Roles; -using Robust.Server.GameObjects; -using Robust.Shared.Prototypes; -namespace Content.Server.Access.Components +namespace Content.Server.Access.Components; + +[RegisterComponent] +[ComponentReference(typeof(SharedIdCardConsoleComponent))] +[Access(typeof(IdCardConsoleSystem))] +public sealed class IdCardConsoleComponent : SharedIdCardConsoleComponent { - [RegisterComponent] - [ComponentReference(typeof(SharedIdCardConsoleComponent))] - public sealed class IdCardConsoleComponent : SharedIdCardConsoleComponent - { - [Dependency] private readonly IEntityManager _entities = default!; - [Dependency] private readonly IAdminLogManager _adminLogger = default!; - [Dependency] private readonly IPrototypeManager _prototypeManager = default!; - - [ViewVariables] private BoundUserInterface? UserInterface => Owner.GetUIOrNull(IdCardConsoleUiKey.Key); - - private StationRecordsSystem? _recordSystem; - private StationSystem? _stationSystem; - - protected override void Initialize() - { - base.Initialize(); - - Owner.EnsureComponentWarn(); - Owner.EnsureComponentWarn(); - - _stationSystem = _entities.EntitySysManager.GetEntitySystem(); - _recordSystem = _entities.EntitySysManager.GetEntitySystem(); - - if (UserInterface != null) - { - UserInterface.OnReceiveMessage += OnUiReceiveMessage; - } - - } - - private void OnUiReceiveMessage(ServerBoundUserInterfaceMessage obj) - { - if (obj.Session.AttachedEntity is not {Valid: true} player) - { - return; - } - - switch (obj.Message) - { - case WriteToTargetIdMessage msg: - TryWriteToTargetId(msg.FullName, msg.JobTitle, msg.AccessList, msg.JobPrototype, player); - UpdateUserInterface(); - break; - } - } - - /// - /// Returns true if there is an ID in and said ID satisfies the requirements of . - /// - private bool PrivilegedIdIsAuthorized() - { - if (!_entities.TryGetComponent(Owner, out AccessReaderComponent? reader)) - { - return true; - } - - var privilegedIdEntity = PrivilegedIdSlot.Item; - var accessSystem = _entities.EntitySysManager.GetEntitySystem(); - return privilegedIdEntity != null && accessSystem.IsAllowed(privilegedIdEntity.Value, reader); - } - - /// - /// Called whenever an access button is pressed, adding or removing that access from the target ID card. - /// Writes data passed from the UI into the ID stored in , if present. - /// - private void TryWriteToTargetId(string newFullName, string newJobTitle, List newAccessList, string newJobProto, EntityUid player) - { - if (TargetIdSlot.Item is not {Valid: true} targetIdEntity || !PrivilegedIdIsAuthorized()) - return; - - var cardSystem = _entities.EntitySysManager.GetEntitySystem(); - cardSystem.TryChangeFullName(targetIdEntity, newFullName, player: player); - cardSystem.TryChangeJobTitle(targetIdEntity, newJobTitle, player: player); - - if (!newAccessList.TrueForAll(x => AccessLevels.Contains(x))) - { - Logger.Warning("Tried to write unknown access tag."); - return; - } - - var accessSystem = _entities.EntitySysManager.GetEntitySystem(); - var oldTags = accessSystem.TryGetTags(targetIdEntity) ?? new List(); - oldTags = oldTags.ToList(); - - if (oldTags.SequenceEqual(newAccessList)) - return; - - var addedTags = newAccessList.Except(oldTags).Select(tag => "+" + tag).ToList(); - var removedTags = oldTags.Except(newAccessList).Select(tag => "-" + tag).ToList(); - accessSystem.TrySetTags(targetIdEntity, newAccessList); - - /*TODO: ECS IdCardConsoleComponent and then log on card ejection, together with the save. - This current implementation is pretty shit as it logs 27 entries (27 lines) if someone decides to give themselves AA*/ - _adminLogger.Add(LogType.Action, LogImpact.Medium, - $"{_entities.ToPrettyString(player):player} has modified {_entities.ToPrettyString(targetIdEntity):entity} with the following accesses: [{String.Join(", ", addedTags.Union(removedTags))}] [{string.Join(", ", newAccessList)}]"); - - UpdateStationRecord(targetIdEntity, newFullName, newJobTitle, newJobProto); - } - - private void UpdateStationRecord(EntityUid idCard, string newFullName, string newJobTitle, string newJobProto) - { - var station = _stationSystem?.GetOwningStation(Owner); - if (station == null - || _recordSystem == null - || !_entities.TryGetComponent(idCard, out StationRecordKeyStorageComponent? keyStorage) - || keyStorage.Key == null - || !_recordSystem.TryGetRecord(station.Value, keyStorage.Key.Value, out GeneralStationRecord? record)) - { - return; - } - - record.Name = newFullName; - record.JobTitle = newJobTitle; - - if (_prototypeManager.TryIndex(newJobProto, out JobPrototype? job)) - { - record.JobPrototype = newJobProto; - record.JobIcon = job.Icon; - } - - _recordSystem.Synchronize(station.Value); - } - - public void UpdateUserInterface() - { - if (!Initialized) - return; - - IdCardConsoleBoundUserInterfaceState newState; - // this could be prettier - if (TargetIdSlot.Item is not {Valid: true} targetIdEntity) - { - var privilegedIdName = string.Empty; - if (PrivilegedIdSlot.Item is {Valid: true} item) - { - privilegedIdName = _entities.GetComponent(item).EntityName; - } - - newState = new IdCardConsoleBoundUserInterfaceState( - PrivilegedIdSlot.HasItem, - PrivilegedIdIsAuthorized(), - false, - null, - null, - null, - string.Empty, - privilegedIdName, - string.Empty); - } - else - { - var targetIdComponent = _entities.GetComponent(targetIdEntity); - var targetAccessComponent = _entities.GetComponent(targetIdEntity); - var name = string.Empty; - if (PrivilegedIdSlot.Item is {Valid: true} item) - name = _entities.GetComponent(item).EntityName; - - var station = _stationSystem?.GetOwningStation(Owner); - var jobProto = string.Empty; - if (_recordSystem != null - && station != null - && _entities.TryGetComponent(targetIdEntity, out StationRecordKeyStorageComponent? keyStorage) - && keyStorage.Key != null - && _recordSystem.TryGetRecord(station.Value, keyStorage.Key.Value, - out GeneralStationRecord? record)) - { - jobProto = record.JobPrototype; - } - - newState = new IdCardConsoleBoundUserInterfaceState( - PrivilegedIdSlot.HasItem, - PrivilegedIdIsAuthorized(), - true, - targetIdComponent.FullName, - targetIdComponent.JobTitle, - targetAccessComponent.Tags.ToArray(), - jobProto, - name, - _entities.GetComponent(targetIdEntity).EntityName); - } - UserInterface?.SetState(newState); - } - } } diff --git a/Content.Server/Access/Systems/IdCardConsoleSystem.cs b/Content.Server/Access/Systems/IdCardConsoleSystem.cs index 92dd6420d3..15578a0b98 100644 --- a/Content.Server/Access/Systems/IdCardConsoleSystem.cs +++ b/Content.Server/Access/Systems/IdCardConsoleSystem.cs @@ -1,21 +1,191 @@ -using Content.Server.Access.Components; +using System.Linq; +using Content.Server.Station.Systems; +using Content.Server.StationRecords; +using Content.Shared.Access.Components; using Content.Shared.Access.Systems; +using Content.Shared.Administration.Logs; +using Content.Shared.Database; +using Content.Shared.Roles; +using Content.Shared.StationRecords; using JetBrains.Annotations; +using Robust.Server.GameObjects; using Robust.Shared.Containers; +using Robust.Shared.Prototypes; +using static Content.Shared.Access.Components.SharedIdCardConsoleComponent; -namespace Content.Server.Access.Systems +namespace Content.Server.Access.Systems; + +[UsedImplicitly] +public sealed class IdCardConsoleSystem : SharedIdCardConsoleSystem { - [UsedImplicitly] - public sealed class IdCardConsoleSystem : SharedIdCardConsoleSystem - { - public override void Initialize() - { - base.Initialize(); + [Dependency] private readonly IPrototypeManager _prototype = default!; + [Dependency] private readonly StationRecordsSystem _record = default!; + [Dependency] private readonly StationSystem _station = default!; + [Dependency] private readonly UserInterfaceSystem _userInterface = default!; + [Dependency] private readonly AccessReaderSystem _accessReader = default!; + [Dependency] private readonly AccessSystem _access = default!; + [Dependency] private readonly IdCardSystem _idCard = default!; + [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; - // one day, maybe bound user interfaces can be shared too. - SubscribeLocalEvent((_, comp, _) => comp.UpdateUserInterface()); - SubscribeLocalEvent((_, comp, _) => comp.UpdateUserInterface()); - SubscribeLocalEvent((_, comp, _) => comp.UpdateUserInterface()); + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnWriteToTargetIdMessage); + + // one day, maybe bound user interfaces can be shared too. + SubscribeLocalEvent(UpdateUserInterface); + SubscribeLocalEvent(UpdateUserInterface); + SubscribeLocalEvent(UpdateUserInterface); + } + + private void OnWriteToTargetIdMessage(EntityUid uid, SharedIdCardConsoleComponent component, WriteToTargetIdMessage args) + { + if (args.Session.AttachedEntity is not { Valid: true } player) + return; + + TryWriteToTargetId(uid, args.FullName, args.JobTitle, args.AccessList, args.JobPrototype, player, component); + + UpdateUserInterface(uid, component, args); + } + + private void UpdateUserInterface(EntityUid uid, SharedIdCardConsoleComponent component, EntityEventArgs args) + { + if (!component.Initialized) + return; + + 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(item).EntityName; + } + + newState = new IdCardConsoleBoundUserInterfaceState( + component.PrivilegedIdSlot.HasItem, + PrivilegedIdIsAuthorized(uid, component), + false, + null, + null, + null, + string.Empty, + privilegedIdName, + string.Empty); } + else + { + var targetIdComponent = EntityManager.GetComponent(targetId); + var targetAccessComponent = EntityManager.GetComponent(targetId); + var name = string.Empty; + if (component.PrivilegedIdSlot.Item is { Valid: true } item) + name = EntityManager.GetComponent(item).EntityName; + + var jobProto = string.Empty; + if (_station.GetOwningStation(uid) is { } station + && EntityManager.TryGetComponent(targetId, out var keyStorage) + && keyStorage.Key != null + && _record.TryGetRecord(station, keyStorage.Key.Value, out var record)) + { + jobProto = record.JobPrototype; + } + + newState = new IdCardConsoleBoundUserInterfaceState( + component.PrivilegedIdSlot.HasItem, + PrivilegedIdIsAuthorized(uid, component), + true, + targetIdComponent.FullName, + targetIdComponent.JobTitle, + targetAccessComponent.Tags.ToArray(), + jobProto, + name, + EntityManager.GetComponent(targetId).EntityName); + } + + _userInterface.TrySetUiState(uid, IdCardConsoleUiKey.Key, newState); + } + + /// + /// Called whenever an access button is pressed, adding or removing that access from the target ID card. + /// Writes data passed from the UI into the ID stored in , if present. + /// + private void TryWriteToTargetId(EntityUid uid, + string newFullName, + string newJobTitle, + List newAccessList, + string newJobProto, + EntityUid player, + SharedIdCardConsoleComponent? component = null) + { + if (!Resolve(uid, ref component)) + return; + + if (component.TargetIdSlot.Item is not { Valid: true } targetId || !PrivilegedIdIsAuthorized(uid, component)) + return; + + _idCard.TryChangeFullName(targetId, newFullName, player: player); + _idCard.TryChangeJobTitle(targetId, newJobTitle, player: player); + + if (!newAccessList.TrueForAll(x => component.AccessLevels.Contains(x))) + { + Logger.Warning("Tried to write unknown access tag."); + return; + } + + var oldTags = _access.TryGetTags(targetId) ?? new List(); + oldTags = oldTags.ToList(); + + if (oldTags.SequenceEqual(newAccessList)) + return; + + var addedTags = newAccessList.Except(oldTags).Select(tag => "+" + tag).ToList(); + var removedTags = oldTags.Except(newAccessList).Select(tag => "-" + tag).ToList(); + _access.TrySetTags(targetId, newAccessList); + + /*TODO: ECS SharedIdCardConsoleComponent and then log on card ejection, together with the save. + This current implementation is pretty shit as it logs 27 entries (27 lines) if someone decides to give themselves AA*/ + _adminLogger.Add(LogType.Action, LogImpact.Medium, + $"{ToPrettyString(player):player} has modified {ToPrettyString(targetId):entity} with the following accesses: [{string.Join(", ", addedTags.Union(removedTags))}] [{string.Join(", ", newAccessList)}]"); + + UpdateStationRecord(uid, targetId, newFullName, newJobTitle, newJobProto); + } + + /// + /// Returns true if there is an ID in and said ID satisfies the requirements of . + /// + private bool PrivilegedIdIsAuthorized(EntityUid uid, SharedIdCardConsoleComponent? component = null) + { + if (!Resolve(uid, ref component)) + return true; + + if (!EntityManager.TryGetComponent(uid, out var reader)) + return true; + + var privilegedId = component.PrivilegedIdSlot.Item; + return privilegedId != null && _accessReader.IsAllowed(privilegedId.Value, reader); + } + + private void UpdateStationRecord(EntityUid uid, EntityUid targetId, string newFullName, string newJobTitle, string newJobProto) + { + if (_station.GetOwningStation(uid) is not { } station + || !EntityManager.TryGetComponent(targetId, out var keyStorage) + || keyStorage.Key is not { } key + || !_record.TryGetRecord(station, key, out var record)) + { + return; + } + + record.Name = newFullName; + record.JobTitle = newJobTitle; + + if (_prototype.TryIndex(newJobProto, out var job)) + { + record.JobPrototype = newJobProto; + record.JobIcon = job.Icon; + } + + _record.Synchronize(station); } }