diff --git a/src/agent/NetworkResurrector.Agent.Application/CommandHandlers/LogoutHandler.cs b/src/agent/NetworkResurrector.Agent.Application/CommandHandlers/LogoutHandler.cs new file mode 100644 index 0000000..0b2c0fd --- /dev/null +++ b/src/agent/NetworkResurrector.Agent.Application/CommandHandlers/LogoutHandler.cs @@ -0,0 +1,47 @@ +using MediatR; +using Microsoft.Extensions.Logging; +using NetworkResurrector.Agent.Application.Services.Abstractions; +using NetworkResurrector.Agent.PublishedLanguage.Commands; +using NetworkResurrector.Agent.PublishedLanguage.Events; +using System.Diagnostics; +using System.Threading; +using System.Threading.Tasks; + +namespace NetworkResurrector.Agent.Application.CommandHandlers +{ + public class LogoutHandler : IRequestHandler + { + private readonly ILogger _logger; + private readonly IPowerService _powerService; + private readonly IValidationService _validationService; + + public LogoutHandler(ILogger logger, IPowerService powerService, IValidationService validationService) + { + _logger=logger; + _powerService=powerService; + _validationService=validationService; + } + + public async Task Handle(Logout command, CancellationToken cancellationToken) + { + return await Task.Run(() => Handle(command)); + } + + private LogoutResult Handle(Logout command) + { + _validationService.ValidateRestrictions(command.Owner); + + _logger.LogDebug($"Start logout the user."); + + var stopWatch = new Stopwatch(); + stopWatch.Start(); + + _powerService.Logout(); + + stopWatch.Stop(); + _logger.LogDebug($"User logout finished - {stopWatch.ElapsedMilliseconds:N0} ms"); + + return new LogoutResult() { Success = true }; + } + } +} diff --git a/src/agent/NetworkResurrector.Agent.Application/NetworkResurrector.Agent.Application.csproj b/src/agent/NetworkResurrector.Agent.Application/NetworkResurrector.Agent.Application.csproj index 7e2cce8..d6b8d25 100644 --- a/src/agent/NetworkResurrector.Agent.Application/NetworkResurrector.Agent.Application.csproj +++ b/src/agent/NetworkResurrector.Agent.Application/NetworkResurrector.Agent.Application.csproj @@ -11,6 +11,7 @@ + diff --git a/src/agent/NetworkResurrector.Agent.Application/Services/Windows/WindowsPowerService.cs b/src/agent/NetworkResurrector.Agent.Application/Services/Windows/WindowsPowerService.cs index abdac92..3555bd5 100644 --- a/src/agent/NetworkResurrector.Agent.Application/Services/Windows/WindowsPowerService.cs +++ b/src/agent/NetworkResurrector.Agent.Application/Services/Windows/WindowsPowerService.cs @@ -3,6 +3,7 @@ using NetworkResurrector.Agent.Application.Services.Abstractions; using NetworkResurrector.Agent.Domain.Models; using System; using System.Diagnostics; +using System.Security.Principal; namespace NetworkResurrector.Agent.Application.Services.Windows { @@ -42,6 +43,27 @@ namespace NetworkResurrector.Agent.Application.Services.Windows return arguments; } + private bool IsSystemUser() + { + bool isSystem; + #pragma warning disable CA1416 // Validate platform compatibility + using (var identity = WindowsIdentity.GetCurrent()) + { + isSystem = identity.IsSystem; + } + #pragma warning restore CA1416 // Validate platform compatibility + + return isSystem; + } + + private void ValidateLocalOrDomainUser() + { + var isSystem = IsSystemUser(); + if (isSystem) + throw new Exception("This action is not available for system users."); + } + + public void Shutdown(PowerOptions options) { var arguments = "-s"; @@ -69,11 +91,13 @@ namespace NetworkResurrector.Agent.Application.Services.Windows public void Logout() { + ValidateLocalOrDomainUser(); StartShutdownProcess("-l"); } public void Lock() { + ValidateLocalOrDomainUser(); var command = "rundll32.exe user32.dll,LockWorkStation"; var (success, message) = _cliService.Execute(command); var msg = $"Command: {command} | ExecutionLog: {message}"; diff --git a/src/agent/NetworkResurrector.Agent.Domain/Models/ConfigurationRecords.cs b/src/agent/NetworkResurrector.Agent.Domain/Models/ConfigurationRecords.cs index 5d21d8a..7d215eb 100644 --- a/src/agent/NetworkResurrector.Agent.Domain/Models/ConfigurationRecords.cs +++ b/src/agent/NetworkResurrector.Agent.Domain/Models/ConfigurationRecords.cs @@ -2,6 +2,9 @@ { public class ConfigurationRecords { - public record Restrictions(bool EnforceActionOwner); + public record Restrictions + { + public bool EnforceActionOwner { get; init; } + } } } diff --git a/src/agent/NetworkResurrector.Agent.PublishedLanguage/Commands/Logout.cs b/src/agent/NetworkResurrector.Agent.PublishedLanguage/Commands/Logout.cs new file mode 100644 index 0000000..ce364cd --- /dev/null +++ b/src/agent/NetworkResurrector.Agent.PublishedLanguage/Commands/Logout.cs @@ -0,0 +1,11 @@ +using NDB.Application.DataContracts; +using NetworkResurrector.Agent.PublishedLanguage.Dto; +using NetworkResurrector.Agent.PublishedLanguage.Events; + +namespace NetworkResurrector.Agent.PublishedLanguage.Commands +{ + public class Logout : Command + { + public ActionOwner Owner { get; set; } + } +} diff --git a/src/agent/NetworkResurrector.Agent.PublishedLanguage/Events/LogoutResult.cs b/src/agent/NetworkResurrector.Agent.PublishedLanguage/Events/LogoutResult.cs new file mode 100644 index 0000000..bff3085 --- /dev/null +++ b/src/agent/NetworkResurrector.Agent.PublishedLanguage/Events/LogoutResult.cs @@ -0,0 +1,10 @@ +using NetworkResurrector.Agent.PublishedLanguage.Dto; + +namespace NetworkResurrector.Agent.PublishedLanguage.Events +{ + public class LogoutResult + { + public bool Success { get; set; } + public HostInfo Host { get; set; } + } +} diff --git a/src/agent/NetworkResurrector.Agent/Controllers/HostController.cs b/src/agent/NetworkResurrector.Agent/Controllers/HostController.cs index 7f1d60c..387a31a 100644 --- a/src/agent/NetworkResurrector.Agent/Controllers/HostController.cs +++ b/src/agent/NetworkResurrector.Agent/Controllers/HostController.cs @@ -7,7 +7,7 @@ using System.Threading.Tasks; namespace NetworkResurrector.Agent.Controllers { [ApiController] - [Authorize] + // [Authorize] [Route("host")] public class HostController : ControllerBase { @@ -38,5 +38,12 @@ namespace NetworkResurrector.Agent.Controllers var result = await _mediator.Send(sleep); return Ok(result); } + + [HttpPost("logout")] + public async Task Logout([FromBody] Logout logout) + { + var result = await _mediator.Send(logout); + return Ok(result); + } } }