From 7c8337146a7960082a710abce87cfd59eb27b144 Mon Sep 17 00:00:00 2001 From: Jared Goodwin Date: Fri, 23 Jun 2023 07:51:47 -0700 Subject: [PATCH] Add DeviceClientDto for transfer from agent to server. Refactor to allow correct scoping of services in tests. --- Agent/Interfaces/IDeviceInformationService.cs | 5 +- Agent/Services/DeviceInfoGeneratorBase.cs | 13 +- .../Linux/DeviceInfoGeneratorLinux.cs | 3 +- .../Services/MacOS/DeviceInfoGeneratorMac.cs | 3 +- .../Windows/DeviceInfoGeneratorWin.cs | 3 +- Server/Components/Devices/DeviceCard.razor | 2 +- Server/Components/Devices/DeviceCard.razor.cs | 3 + Server/Hubs/AgentHub.cs | 9 +- Server/Services/DataService.cs | 126 +++++++++++------- Shared/Dtos/DeviceClientDto.cs | 73 ++++++++++ Shared/Extensions/DeviceExtensions.cs | 30 +++++ Shared/Models/Device.cs | 25 +++- Tests/LoadTester/Program.cs | 2 +- Tests/Server.Tests/AgentHubTests.cs | 7 +- Tests/Server.Tests/CircuitConnectionTests.cs | 102 +++++++++----- Tests/Server.Tests/DataServiceTests.cs | 7 +- Tests/Server.Tests/TestData.cs | 82 ++++++------ 17 files changed, 350 insertions(+), 145 deletions(-) create mode 100644 Shared/Dtos/DeviceClientDto.cs create mode 100644 Shared/Extensions/DeviceExtensions.cs diff --git a/Agent/Interfaces/IDeviceInformationService.cs b/Agent/Interfaces/IDeviceInformationService.cs index bd58f180..db71ce0e 100644 --- a/Agent/Interfaces/IDeviceInformationService.cs +++ b/Agent/Interfaces/IDeviceInformationService.cs @@ -1,4 +1,5 @@ -using Remotely.Shared.Models; +using Remotely.Shared.Dtos; +using Remotely.Shared.Models; using System; using System.Collections.Generic; using System.Linq; @@ -9,6 +10,6 @@ namespace Remotely.Agent.Interfaces { public interface IDeviceInformationService { - Task CreateDevice(string deviceId, string orgId); + Task CreateDevice(string deviceId, string orgId); } } diff --git a/Agent/Services/DeviceInfoGeneratorBase.cs b/Agent/Services/DeviceInfoGeneratorBase.cs index e96bbaa2..c27a12d1 100644 --- a/Agent/Services/DeviceInfoGeneratorBase.cs +++ b/Agent/Services/DeviceInfoGeneratorBase.cs @@ -1,4 +1,5 @@ using Microsoft.Extensions.Logging; +using Remotely.Shared.Dtos; using Remotely.Shared.Models; using Remotely.Shared.Utilities; using System; @@ -21,21 +22,21 @@ namespace Remotely.Agent.Services _logger = logger; } - protected Device GetDeviceBase(string deviceID, string orgID) + protected DeviceClientDto GetDeviceBase(string deviceID, string orgID) { - return new Device() + return new DeviceClientDto() { - ID = deviceID, + Id = deviceID, DeviceName = Environment.MachineName, Platform = EnvironmentHelper.Platform.ToString(), ProcessorCount = Environment.ProcessorCount, - OSArchitecture = RuntimeInformation.OSArchitecture, - OSDescription = RuntimeInformation.OSDescription, + OsArchitecture = RuntimeInformation.OSArchitecture, + OsDescription = RuntimeInformation.OSDescription, Is64Bit = Environment.Is64BitOperatingSystem, IsOnline = true, MacAddresses = GetMacAddresses().ToArray(), - OrganizationID = orgID, + OrganizationId = orgID, AgentVersion = AppVersionHelper.GetAppVersion() }; } diff --git a/Agent/Services/Linux/DeviceInfoGeneratorLinux.cs b/Agent/Services/Linux/DeviceInfoGeneratorLinux.cs index 110b2709..fe5fab19 100644 --- a/Agent/Services/Linux/DeviceInfoGeneratorLinux.cs +++ b/Agent/Services/Linux/DeviceInfoGeneratorLinux.cs @@ -1,5 +1,6 @@ using Microsoft.Extensions.Logging; using Remotely.Agent.Interfaces; +using Remotely.Shared.Dtos; using Remotely.Shared.Models; using Remotely.Shared.Services; using Remotely.Shared.Utilities; @@ -26,7 +27,7 @@ namespace Remotely.Agent.Services.Linux _cpuUtilSampler = cpuUtilSampler; } - public Task CreateDevice(string deviceId, string orgId) + public Task CreateDevice(string deviceId, string orgId) { var device = GetDeviceBase(deviceId, orgId); diff --git a/Agent/Services/MacOS/DeviceInfoGeneratorMac.cs b/Agent/Services/MacOS/DeviceInfoGeneratorMac.cs index f7471c70..dc9efcbe 100644 --- a/Agent/Services/MacOS/DeviceInfoGeneratorMac.cs +++ b/Agent/Services/MacOS/DeviceInfoGeneratorMac.cs @@ -1,5 +1,6 @@ using Microsoft.Extensions.Logging; using Remotely.Agent.Interfaces; +using Remotely.Shared.Dtos; using Remotely.Shared.Models; using Remotely.Shared.Services; using System; @@ -17,7 +18,7 @@ namespace Remotely.Agent.Services.MacOS { _processInvoker = processInvoker; } - public async Task CreateDevice(string deviceId, string orgId) + public async Task CreateDevice(string deviceId, string orgId) { var device = GetDeviceBase(deviceId, orgId); diff --git a/Agent/Services/Windows/DeviceInfoGeneratorWin.cs b/Agent/Services/Windows/DeviceInfoGeneratorWin.cs index 8b47d8a6..daae8753 100644 --- a/Agent/Services/Windows/DeviceInfoGeneratorWin.cs +++ b/Agent/Services/Windows/DeviceInfoGeneratorWin.cs @@ -1,6 +1,7 @@ using Immense.RemoteControl.Desktop.Native.Windows; using Microsoft.Extensions.Logging; using Remotely.Agent.Interfaces; +using Remotely.Shared.Dtos; using Remotely.Shared.Models; using System; using System.Linq; @@ -20,7 +21,7 @@ namespace Remotely.Agent.Services.Windows _cpuUtilSampler = cpuUtilSampler; } - public Task CreateDevice(string deviceId, string orgId) + public Task CreateDevice(string deviceId, string orgId) { var device = GetDeviceBase(deviceId, orgId); diff --git a/Server/Components/Devices/DeviceCard.razor b/Server/Components/Devices/DeviceCard.razor index 9ba98746..fffab6b4 100644 --- a/Server/Components/Devices/DeviceCard.razor +++ b/Server/Components/Devices/DeviceCard.razor @@ -234,7 +234,7 @@ - @foreach (var group in DataService.GetDeviceGroups(Username)) + @foreach (var group in _deviceGroups) { } diff --git a/Server/Components/Devices/DeviceCard.razor.cs b/Server/Components/Devices/DeviceCard.razor.cs index fb6dacb7..b733a517 100644 --- a/Server/Components/Devices/DeviceCard.razor.cs +++ b/Server/Components/Devices/DeviceCard.razor.cs @@ -28,6 +28,8 @@ namespace Remotely.Server.Components.Devices private ElementReference _card; private Version _currentVersion = new(); private Theme _theme; + private DeviceGroup[] _deviceGroups = Array.Empty(); + [Parameter] public Device Device { get; set; } @@ -78,6 +80,7 @@ namespace Remotely.Server.Components.Devices await base.OnInitializedAsync(); _theme = await AppState.GetEffectiveTheme(); _currentVersion = UpgradeService.GetCurrentVersion(); + _deviceGroups = DataService.GetDeviceGroups(Username); AppState.PropertyChanged += AppState_PropertyChanged; CircuitConnection.MessageReceived += CircuitConnection_MessageReceived; } diff --git a/Server/Hubs/AgentHub.cs b/Server/Hubs/AgentHub.cs index 84e57a40..0deea6ed 100644 --- a/Server/Hubs/AgentHub.cs +++ b/Server/Hubs/AgentHub.cs @@ -5,6 +5,7 @@ using Microsoft.Extensions.Logging; using Remotely.Server.Models; using Remotely.Server.Services; using Remotely.Shared; +using Remotely.Shared.Dtos; using Remotely.Shared.Enums; using Remotely.Shared.Models; using Remotely.Shared.Utilities; @@ -87,11 +88,11 @@ namespace Remotely.Server.Hubs } } - public async Task DeviceCameOnline(Device device) + public async Task DeviceCameOnline(DeviceClientDto device) { try { - if (CheckForDeviceBan(device.ID, device.DeviceName)) + if (CheckForDeviceBan(device.Id, device.DeviceName)) { return false; } @@ -144,9 +145,9 @@ namespace Remotely.Server.Hubs return false; } - public async Task DeviceHeartbeat(Device device) + public async Task DeviceHeartbeat(DeviceClientDto device) { - if (CheckForDeviceBan(device.ID, device.DeviceName)) + if (CheckForDeviceBan(device.Id, device.DeviceName)) { return; } diff --git a/Server/Services/DataService.cs b/Server/Services/DataService.cs index 21bcb12a..43d79727 100644 --- a/Server/Services/DataService.cs +++ b/Server/Services/DataService.cs @@ -10,6 +10,7 @@ using Microsoft.Extensions.Logging; using Remotely.Server.Data; using Remotely.Server.Models; using Remotely.Shared; +using Remotely.Shared.Dtos; using Remotely.Shared.Enums; using Remotely.Shared.Models; using Remotely.Shared.Utilities; @@ -27,10 +28,10 @@ namespace Remotely.Server.Services Task AddAlert(string deviceID, string organizationID, string alertMessage, string details = null); bool AddDeviceGroup(string orgID, DeviceGroup deviceGroup, out string deviceGroupID, out string errorMessage); - + Task AddDeviceToGroup(string deviceId, string groupId); InviteLink AddInvite(string orgID, InviteViewModel invite); - Task> AddOrUpdateDevice(Device device); + Task> AddOrUpdateDevice(DeviceClientDto device); Task AddOrUpdateSavedScript(SavedScript script, string userId); @@ -305,6 +306,34 @@ namespace Remotely.Server.Services return true; } + public async Task AddDeviceToGroup(string deviceId, string groupId) + { + using var context = _appDbFactory.GetContext(); + var device = await context.Devices.FirstOrDefaultAsync(x => x.ID == deviceId); + + if (device is null) + { + return Result.Fail("Device not found."); + } + + var group = await context.DeviceGroups.FirstOrDefaultAsync(x => + x.OrganizationID == device.OrganizationID && + x.ID == groupId); + + if (group is null) + { + return Result.Fail("Group not found."); + } + + group.Devices ??= new(); + group.Devices.Add(device); + device.DeviceGroup = group; + device.DeviceGroupID = group.ID; + await context.SaveChangesAsync(); + + return Result.Ok(); + } + public InviteLink AddInvite(string orgID, InviteViewModel invite) { using var dbContext = _appDbFactory.GetContext(); @@ -327,61 +356,62 @@ namespace Remotely.Server.Services return inviteLink; } - public async Task> AddOrUpdateDevice(Device device) + public async Task> AddOrUpdateDevice(DeviceClientDto deviceDto) { using var dbContext = _appDbFactory.GetContext(); - var resultDevice = await dbContext.Devices.FindAsync(device.ID); + var device = await dbContext.Devices.FindAsync(deviceDto.Id); - if (resultDevice != null) + if (device is null) { - resultDevice.CurrentUser = device.CurrentUser; - resultDevice.DeviceName = device.DeviceName; - resultDevice.Drives = device.Drives; - resultDevice.CpuUtilization = device.CpuUtilization; - resultDevice.UsedMemory = device.UsedMemory; - resultDevice.UsedStorage = device.UsedStorage; - resultDevice.Is64Bit = device.Is64Bit; - resultDevice.IsOnline = true; - resultDevice.OSArchitecture = device.OSArchitecture; - resultDevice.OSDescription = device.OSDescription; - resultDevice.Platform = device.Platform; - resultDevice.ProcessorCount = device.ProcessorCount; - resultDevice.PublicIP = device.PublicIP; - resultDevice.TotalMemory = device.TotalMemory; - resultDevice.TotalStorage = device.TotalStorage; - resultDevice.AgentVersion = device.AgentVersion; - resultDevice.MacAddresses = device.MacAddresses ?? Array.Empty(); - resultDevice.DeviceGroupID = device.DeviceGroupID; - resultDevice.LastOnline = DateTimeOffset.Now; - } - else - { - device.LastOnline = DateTimeOffset.Now; - if (_hostEnvironment.IsDevelopment() && dbContext.Organizations.Any()) + device = new Device { - var org = await dbContext.Organizations.FirstOrDefaultAsync(); - device.Organization = org; - device.OrganizationID = org?.ID; - } - - resultDevice = device; - - if (!await dbContext.Organizations.AnyAsync(x => x.ID == device.OrganizationID)) - { - _logger.LogInformation( - "Unable to add device {deviceName} because organization {organizationID}" + - "does not exist. Device ID: {ID}.", - device.DeviceName, - device.OrganizationID, - device.ID); - - return Result.Fail("Organization does not exist."); - } + OrganizationID = deviceDto.OrganizationId, + ID = deviceDto.Id, + }; await dbContext.Devices.AddAsync(device); } + + device.CurrentUser = deviceDto.CurrentUser; + device.DeviceName = deviceDto.DeviceName; + device.Drives = deviceDto.Drives; + device.CpuUtilization = deviceDto.CpuUtilization; + device.UsedMemory = deviceDto.UsedMemory; + device.UsedStorage = deviceDto.UsedStorage; + device.Is64Bit = deviceDto.Is64Bit; + device.IsOnline = true; + device.OSArchitecture = deviceDto.OsArchitecture; + device.OSDescription = deviceDto.OsDescription; + device.Platform = deviceDto.Platform; + device.ProcessorCount = deviceDto.ProcessorCount; + device.PublicIP = deviceDto.PublicIP; + device.TotalMemory = deviceDto.TotalMemory; + device.TotalStorage = deviceDto.TotalStorage; + device.AgentVersion = deviceDto.AgentVersion; + device.MacAddresses = deviceDto.MacAddresses ?? Array.Empty(); + device.LastOnline = DateTimeOffset.Now; + + if (_hostEnvironment.IsDevelopment() && dbContext.Organizations.Any()) + { + var org = await dbContext.Organizations.FirstOrDefaultAsync(); + device.Organization = org; + device.OrganizationID = org?.ID; + } + + if (!await dbContext.Organizations.AnyAsync(x => x.ID == device.OrganizationID)) + { + _logger.LogInformation( + "Unable to add device {deviceName} because organization {organizationID}" + + "does not exist. Device ID: {ID}.", + device.DeviceName, + device.OrganizationID, + device.ID); + + return Result.Fail("Organization does not exist."); + } + await dbContext.SaveChangesAsync(); - return Result.Ok(resultDevice); + return Result.Ok(device); } public async Task AddOrUpdateSavedScript(SavedScript script, string userId) diff --git a/Shared/Dtos/DeviceClientDto.cs b/Shared/Dtos/DeviceClientDto.cs new file mode 100644 index 00000000..cec6402c --- /dev/null +++ b/Shared/Dtos/DeviceClientDto.cs @@ -0,0 +1,73 @@ +using Remotely.Shared.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Runtime.Serialization; +using System.Text; +using System.Text.Json; +using System.Threading.Tasks; + +namespace Remotely.Shared.Dtos +{ + [DataContract] + public class DeviceClientDto + { + [DataMember] + public string AgentVersion { get; set; } = string.Empty; + + [DataMember] + public double CpuUtilization { get; set; } + + [DataMember] + public string CurrentUser { get; set; } = string.Empty; + + [DataMember] + public string DeviceName { get; set; } = string.Empty; + + [DataMember] + public List Drives { get; set; } = new(); + + [DataMember] + public string Id { get; set; } = string.Empty; + + [DataMember] + public bool Is64Bit { get; set; } + + [DataMember] + public bool IsOnline { get; set; } + + [DataMember] + public string[] MacAddresses { get; set; } = Array.Empty(); + + [DataMember] + public string OrganizationId { get; set; } = string.Empty; + + [DataMember] + public Architecture OsArchitecture { get; set; } + + [DataMember] + public string OsDescription { get; set; } = string.Empty; + + [DataMember] + public string Platform { get; set; } = string.Empty; + + [DataMember] + public int ProcessorCount { get; set; } + + [DataMember] + public string PublicIP { get; set; } = string.Empty; + + [DataMember] + public double TotalMemory { get; set; } + + [DataMember] + public double TotalStorage { get; set; } + + [DataMember] + public double UsedMemory { get; set; } + + [DataMember] + public double UsedStorage { get; set; } + } +} diff --git a/Shared/Extensions/DeviceExtensions.cs b/Shared/Extensions/DeviceExtensions.cs new file mode 100644 index 00000000..a9bcbafa --- /dev/null +++ b/Shared/Extensions/DeviceExtensions.cs @@ -0,0 +1,30 @@ +using Remotely.Shared.Dtos; +using Remotely.Shared.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.Json; +using System.Threading.Tasks; + +namespace Remotely.Shared.Extensions +{ + public static class DeviceExtensions + { + private static JsonSerializerOptions _serializerOptions = new() + { + PropertyNameCaseInsensitive = true + }; + + /// + /// A helper method for creating a DeviceClientDto from a Device entity. + /// + /// + /// + public static DeviceClientDto ToDto(this Device device) + { + var json = JsonSerializer.Serialize(device, _serializerOptions); + return JsonSerializer.Deserialize(json, _serializerOptions); + } + } +} diff --git a/Shared/Models/Device.cs b/Shared/Models/Device.cs index 7b65fae7..ffd2dc7e 100644 --- a/Shared/Models/Device.cs +++ b/Shared/Models/Device.cs @@ -3,6 +3,7 @@ using Remotely.Shared.Enums; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; using System.Runtime.InteropServices; using System.Text.Json.Serialization; @@ -107,7 +108,17 @@ namespace Remotely.Shared.Models [Sortable] [Display(Name = "Memory Used %")] - public double UsedMemoryPercent => UsedMemory / TotalMemory; + public double UsedMemoryPercent + { + get + { + if (TotalMemory == 0) + { + return 0; + } + return UsedMemory / TotalMemory; + } + } [Sortable] [Display(Name = "Storage Used")] @@ -115,6 +126,16 @@ namespace Remotely.Shared.Models [Sortable] [Display(Name = "Storage Used %")] - public double UsedStoragePercent => UsedStorage / TotalStorage; + public double UsedStoragePercent + { + get + { + if (TotalStorage == 0) + { + return 0; + } + return UsedStorage / TotalStorage; + } + } } } \ No newline at end of file diff --git a/Tests/LoadTester/Program.cs b/Tests/LoadTester/Program.cs index 3b341c0c..dc22a163 100644 --- a/Tests/LoadTester/Program.cs +++ b/Tests/LoadTester/Program.cs @@ -116,7 +116,7 @@ internal class Program { try { - var currentInfo = await _deviceInfo.CreateDevice(device.ID, _organizationId); + var currentInfo = await _deviceInfo.CreateDevice(device.Id, _organizationId); currentInfo.DeviceName = device.DeviceName; await hubConnection.SendAsync("DeviceHeartbeat", currentInfo); } diff --git a/Tests/Server.Tests/AgentHubTests.cs b/Tests/Server.Tests/AgentHubTests.cs index 278d8af4..0b7fa32d 100644 --- a/Tests/Server.Tests/AgentHubTests.cs +++ b/Tests/Server.Tests/AgentHubTests.cs @@ -1,4 +1,4 @@ -using Immense.RemoteControl.Server.Abstractions; +using Remotely.Shared.Extensions; using Immense.RemoteControl.Server.Hubs; using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.SignalR; @@ -9,6 +9,7 @@ using Moq; using Remotely.Server.Hubs; using Remotely.Server.Models; using Remotely.Server.Services; +using Remotely.Shared.Dtos; using Remotely.Shared.Models; using System; using System.Collections.Generic; @@ -57,7 +58,7 @@ namespace Remotely.Tests hubClients.Setup(x => x.Caller).Returns(caller.Object); hub.Clients = hubClients.Object; - Assert.IsFalse(await hub.DeviceCameOnline(_testData.Org1Device1)); + Assert.IsFalse(await hub.DeviceCameOnline(_testData.Org1Device1.ToDto())); hubClients.Verify(x => x.Caller, Times.Once); caller.Verify(x => x.SendCoreAsync("UninstallAgent", It.IsAny(), It.IsAny()), Times.Once); } @@ -94,7 +95,7 @@ namespace Remotely.Tests hubClients.Setup(x => x.Caller).Returns(caller.Object); hub.Clients = hubClients.Object; - Assert.IsFalse(await hub.DeviceCameOnline(_testData.Org1Device1)); + Assert.IsFalse(await hub.DeviceCameOnline(_testData.Org1Device1.ToDto())); hubClients.Verify(x => x.Caller, Times.Once); caller.Verify(x => x.SendCoreAsync("UninstallAgent", It.IsAny(), It.IsAny()), Times.Once); } diff --git a/Tests/Server.Tests/CircuitConnectionTests.cs b/Tests/Server.Tests/CircuitConnectionTests.cs index 21007cfd..0b64025b 100644 --- a/Tests/Server.Tests/CircuitConnectionTests.cs +++ b/Tests/Server.Tests/CircuitConnectionTests.cs @@ -10,6 +10,8 @@ using Moq; using Remotely.Server.Hubs; using Remotely.Server.Services; using Remotely.Server.Tests.Mocks; +using Remotely.Shared.Dtos; +using Remotely.Shared.Extensions; using Remotely.Shared.Models; using Remotely.Tests; using System; @@ -88,13 +90,20 @@ namespace Remotely.Server.Tests _testData.Org2Device1.PublicIP = "142.251.33.110"; - var updateResult = await _dataService.AddOrUpdateDevice(_testData.Org1Device1); + var updateResult = await _dataService.AddOrUpdateDevice(_testData.Org1Device1.ToDto()); Assert.IsTrue(updateResult.IsSuccess); - updateResult = await _dataService.AddOrUpdateDevice(_testData.Org1Device2); + updateResult = await _dataService.AddOrUpdateDevice(_testData.Org1Device2.ToDto()); Assert.IsTrue(updateResult.IsSuccess); - updateResult = await _dataService.AddOrUpdateDevice(_testData.Org2Device1); + updateResult = await _dataService.AddOrUpdateDevice(_testData.Org2Device1.ToDto()); Assert.IsTrue(updateResult.IsSuccess); + var addGroupResult = await _dataService.AddDeviceToGroup(_testData.Org1Device1.ID, _testData.Org1Group1.ID); + Assert.IsTrue(addGroupResult.IsSuccess); + addGroupResult = await _dataService.AddDeviceToGroup(_testData.Org1Device2.ID, _testData.Org1Group1.ID); + Assert.IsTrue(addGroupResult.IsSuccess); + addGroupResult = await _dataService.AddDeviceToGroup(_testData.Org2Device1.ID, _testData.Org2Group1.ID); + Assert.IsTrue(addGroupResult.IsSuccess); + var wakeResult = await _circuitConnection.WakeDevice(_testData.Org1Device1); Assert.IsFalse(wakeResult.IsSuccess); @@ -112,29 +121,32 @@ namespace Remotely.Server.Tests // Offline device. _testData.Org1Device1.PublicIP = "142.251.33.110"; _testData.Org1Device1.MacAddresses = new[] { macAddress }; - _testData.Org1Device1.DeviceGroupID = _testData.Org1Group1.ID; // Online device. _testData.Org1Device2.PublicIP = "142.251.33.110"; // Device in another org that shouldn't receive the command. _testData.Org2Device1.PublicIP = "142.251.33.110"; + // Offline device in the same group as user. + var addGroupResult = await _dataService.AddDeviceToGroup(_testData.Org1Device1.ID, _testData.Org1Group1.ID); + Assert.IsTrue(addGroupResult.IsSuccess); + var addToGroupResult = _dataService.AddUserToDeviceGroup( _testData.Org1Id, _testData.Org1Group1.ID, _testData.Org1User1.UserName, out _); - var updateResult = await _dataService.AddOrUpdateDevice(_testData.Org1Device1); + var updateResult = await _dataService.AddOrUpdateDevice(_testData.Org1Device1.ToDto()); Assert.IsTrue(updateResult.IsSuccess); - updateResult = await _dataService.AddOrUpdateDevice(_testData.Org1Device2); + updateResult = await _dataService.AddOrUpdateDevice(_testData.Org1Device2.ToDto()); Assert.IsTrue(updateResult.IsSuccess); - updateResult = await _dataService.AddOrUpdateDevice(_testData.Org2Device1); + updateResult = await _dataService.AddOrUpdateDevice(_testData.Org2Device1.ToDto()); Assert.IsTrue(updateResult.IsSuccess); _agentSessionCache .Setup(x => x.GetAllDevices()) - .Returns(new[] - { + .Returns(new[] + { _testData.Org1Device2, _testData.Org2Device1 }); @@ -163,9 +175,9 @@ namespace Remotely.Server.Tests _agentHubContextFixture.SingleClientProxyMock .Verify(x => x.SendCoreAsync( - "WakeDevice", + "WakeDevice", new object[] { macAddress }, - default), + default), Times.Once); _agentHubContextFixture.SingleClientProxyMock.VerifyNoOtherCalls(); @@ -183,11 +195,6 @@ namespace Remotely.Server.Tests // Offline device. _testData.Org1Device1.PublicIP = "142.251.33.110"; _testData.Org1Device1.MacAddresses = new[] { macAddress }; - _testData.Org1Device1.DeviceGroupID = _testData.Org1Group1.ID; - // Online device. - _testData.Org1Device2.DeviceGroupID = _testData.Org1Group1.ID; - // Device in another org that shouldn't receive the command. - _testData.Org2Device1.DeviceGroupID = _testData.Org2Group1.ID; var addToGroupResult = _dataService.AddUserToDeviceGroup( _testData.Org1Id, @@ -195,13 +202,20 @@ namespace Remotely.Server.Tests _testData.Org1User1.UserName, out _); - var updateResult = await _dataService.AddOrUpdateDevice(_testData.Org1Device1); - Assert.IsTrue(updateResult.IsSuccess); - updateResult = await _dataService.AddOrUpdateDevice(_testData.Org1Device2); - Assert.IsTrue(updateResult.IsSuccess); - updateResult = await _dataService.AddOrUpdateDevice(_testData.Org2Device1); + var updateResult = await _dataService.AddOrUpdateDevice(_testData.Org1Device1.ToDto()); Assert.IsTrue(updateResult.IsSuccess); + // Offline device. + var addGroupResult = await _dataService.AddDeviceToGroup(_testData.Org1Device1.ID, _testData.Org1Group1.ID); + Assert.IsTrue(addGroupResult.IsSuccess); + // Online device in the same group and org. Should relay wake command. + addGroupResult = await _dataService.AddDeviceToGroup(_testData.Org1Device2.ID, _testData.Org1Group1.ID); + Assert.IsTrue(addGroupResult.IsSuccess); + // Online device in a different org. Should not receive wake command. + addGroupResult = await _dataService.AddDeviceToGroup(_testData.Org2Device1.ID, _testData.Org2Group1.ID); + Assert.IsTrue(addGroupResult.IsSuccess); + + _agentSessionCache .Setup(x => x.GetAllDevices()) .Returns(new[] @@ -267,13 +281,26 @@ namespace Remotely.Server.Tests _testData.Org1User1.UserName, out _); - var updateResult = await _dataService.AddOrUpdateDevice(_testData.Org1Device1); + var updateResult = await _dataService.AddOrUpdateDevice(_testData.Org1Device1.ToDto()); Assert.IsTrue(updateResult.IsSuccess); - updateResult = await _dataService.AddOrUpdateDevice(_testData.Org1Device2); + updateResult = await _dataService.AddOrUpdateDevice(_testData.Org1Device2.ToDto()); Assert.IsTrue(updateResult.IsSuccess); - updateResult = await _dataService.AddOrUpdateDevice(_testData.Org2Device1); + updateResult = await _dataService.AddOrUpdateDevice(_testData.Org2Device1.ToDto()); Assert.IsTrue(updateResult.IsSuccess); + + // Offline device. + var addGroupResult = await _dataService.AddDeviceToGroup(_testData.Org1Device1.ID, _testData.Org1Group1.ID); + Assert.IsTrue(addGroupResult.IsSuccess); + + // Online device in a different group. Should not recieve wake command. + addGroupResult = await _dataService.AddDeviceToGroup(_testData.Org1Device2.ID, _testData.Org1Group2.ID); + Assert.IsTrue(addGroupResult.IsSuccess); + + // Online device in a different org. Should not recieve wake command. + addGroupResult = await _dataService.AddDeviceToGroup(_testData.Org2Device1.ID, _testData.Org2Group1.ID); + Assert.IsTrue(addGroupResult.IsSuccess); + _agentSessionCache .Setup(x => x.GetAllDevices()) .Returns(new[] @@ -312,17 +339,21 @@ namespace Remotely.Server.Tests // Device in another org that shouldn't receive the command. _testData.Org2Device1.PublicIP = "142.251.33.110"; + // Offline device in the same group as user. + var addGroupResult = await _dataService.AddDeviceToGroup(_testData.Org1Device1.ID, _testData.Org1Group1.ID); + Assert.IsTrue(addGroupResult.IsSuccess); + var addToGroupResult = _dataService.AddUserToDeviceGroup( _testData.Org1Id, _testData.Org1Group1.ID, _testData.Org1User1.UserName, out _); - var updateResult = await _dataService.AddOrUpdateDevice(_testData.Org1Device1); + var updateResult = await _dataService.AddOrUpdateDevice(_testData.Org1Device1.ToDto()); Assert.IsTrue(updateResult.IsSuccess); - updateResult = await _dataService.AddOrUpdateDevice(_testData.Org1Device2); + updateResult = await _dataService.AddOrUpdateDevice(_testData.Org1Device2.ToDto()); Assert.IsTrue(updateResult.IsSuccess); - updateResult = await _dataService.AddOrUpdateDevice(_testData.Org2Device1); + updateResult = await _dataService.AddOrUpdateDevice(_testData.Org2Device1.ToDto()); Assert.IsTrue(updateResult.IsSuccess); _agentSessionCache @@ -389,13 +420,23 @@ namespace Remotely.Server.Tests _testData.Org1User1.UserName, out _); - var updateResult = await _dataService.AddOrUpdateDevice(_testData.Org1Device1); + var updateResult = await _dataService.AddOrUpdateDevice(_testData.Org1Device1.ToDto()); Assert.IsTrue(updateResult.IsSuccess); - updateResult = await _dataService.AddOrUpdateDevice(_testData.Org1Device2); + updateResult = await _dataService.AddOrUpdateDevice(_testData.Org1Device2.ToDto()); Assert.IsTrue(updateResult.IsSuccess); - updateResult = await _dataService.AddOrUpdateDevice(_testData.Org2Device1); + updateResult = await _dataService.AddOrUpdateDevice(_testData.Org2Device1.ToDto()); Assert.IsTrue(updateResult.IsSuccess); + // Offline device. + var addGroupResult = await _dataService.AddDeviceToGroup(_testData.Org1Device1.ID, _testData.Org1Group1.ID); + Assert.IsTrue(addGroupResult.IsSuccess); + // Online device in the same group and org. Should relay wake command. + addGroupResult = await _dataService.AddDeviceToGroup(_testData.Org1Device2.ID, _testData.Org1Group1.ID); + Assert.IsTrue(addGroupResult.IsSuccess); + // Online device in a different org. Should not receive wake command. + addGroupResult = await _dataService.AddDeviceToGroup(_testData.Org2Device1.ID, _testData.Org2Group1.ID); + Assert.IsTrue(addGroupResult.IsSuccess); + _agentSessionCache .Setup(x => x.GetAllDevices()) .Returns(new[] @@ -437,6 +478,5 @@ namespace Remotely.Server.Tests _agentHubContextFixture.HubContextMock.VerifyNoOtherCalls(); _agentSessionCache.VerifyNoOtherCalls(); } - } } diff --git a/Tests/Server.Tests/DataServiceTests.cs b/Tests/Server.Tests/DataServiceTests.cs index 245285bc..215d027b 100644 --- a/Tests/Server.Tests/DataServiceTests.cs +++ b/Tests/Server.Tests/DataServiceTests.cs @@ -2,6 +2,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; using Remotely.Server.Services; +using Remotely.Shared.Dtos; using Remotely.Shared.Models; using Remotely.Shared.Utilities; using System; @@ -35,10 +36,10 @@ namespace Remotely.Tests Assert.IsNull(storedDevice); - var newDevice = new Device() + var newDevice = new DeviceClientDto() { - ID = _newDeviceID, - OrganizationID = _testData.Org1Id, + Id = _newDeviceID, + OrganizationId = _testData.Org1Id, DeviceName = Environment.MachineName, Is64Bit = Environment.Is64BitOperatingSystem }; diff --git a/Tests/Server.Tests/TestData.cs b/Tests/Server.Tests/TestData.cs index 0b161d60..968e315a 100644 --- a/Tests/Server.Tests/TestData.cs +++ b/Tests/Server.Tests/TestData.cs @@ -1,9 +1,11 @@ using Microsoft.AspNetCore.Identity; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Moq; using Remotely.Server.Areas.Identity.Pages.Account.Manage; using Remotely.Server.Data; using Remotely.Server.Services; +using Remotely.Shared.Dtos; using Remotely.Shared.Models; using System; using System.Linq; @@ -26,19 +28,11 @@ namespace Remotely.Tests UserOptions = new RemotelyUserOptions() }; - public RemotelyUser Org1Admin2 { get; private set; } + public RemotelyUser Org1Admin2 { get; private set; } - public Device Org1Device1 { get; private set; } = new Device() - { - ID = "Org1Device1", - DeviceName = "Org1Device1Name" - }; + public Device Org1Device1 { get; private set; } - public Device Org1Device2 { get; private set; } = new Device() - { - ID = "Org1Device2", - DeviceName = "Org1Device2Name" - }; + public Device Org1Device2 { get; private set; } public DeviceGroup Org1Group1 { get; private set; } = new DeviceGroup() { @@ -71,17 +65,9 @@ namespace Remotely.Tests public RemotelyUser Org2Admin2 { get; private set; } - public Device Org2Device1 { get; private set; } = new Device() - { - ID = "Org2Device1", - DeviceName = "Org2Device1Name" - }; + public Device Org2Device1 { get; private set; } - public Device Org2Device2 { get; private set; } = new Device() - { - ID = "Org2Device2", - DeviceName = "Org2Device2Name" - }; + public Device Org2Device2 { get; private set; } public DeviceGroup Org2Group1 { get; private set; } = new DeviceGroup() { @@ -100,17 +86,10 @@ namespace Remotely.Tests public void ClearData() { - var dbContext = IoCActivator.ServiceProvider.GetRequiredService(); - dbContext.Devices.RemoveRange(dbContext.Devices.ToList()); - dbContext.DeviceGroups.RemoveRange(dbContext.DeviceGroups.ToList()); - dbContext.Users.RemoveRange(dbContext.Users.ToList()); - dbContext.Organizations.RemoveRange(dbContext.Organizations.ToList()); - dbContext.Alerts.RemoveRange(dbContext.Alerts.ToList()); - dbContext.ScriptResults.RemoveRange(dbContext.ScriptResults.ToList()); - dbContext.ScriptRuns.RemoveRange(dbContext.ScriptRuns.ToList()); - dbContext.ScriptSchedules.RemoveRange(dbContext.ScriptSchedules.ToList()); - dbContext.SavedScripts.RemoveRange(dbContext.SavedScripts.ToList()); - dbContext.SaveChanges(); + using var scope = IoCActivator.ServiceProvider.CreateScope(); + using var dbContext = scope.ServiceProvider.GetRequiredService(); + dbContext.Database.EnsureDeleted(); + dbContext.Database.EnsureCreated(); } @@ -118,8 +97,9 @@ namespace Remotely.Tests { ClearData(); + using var scope = IoCActivator.ServiceProvider.CreateScope(); + using var userManager = scope.ServiceProvider.GetRequiredService>(); var dataService = IoCActivator.ServiceProvider.GetRequiredService(); - var userManager = IoCActivator.ServiceProvider.GetRequiredService>(); var emailSender = IoCActivator.ServiceProvider.GetRequiredService(); // Organization 1 @@ -134,10 +114,20 @@ namespace Remotely.Tests await dataService.CreateUser("org1testuser2@test.com", false, Org1Admin1.OrganizationID); Org1User2 = dataService.GetUserByNameWithOrg("org1testuser2@test.com"); - Org1Device1.OrganizationID = Org1Admin1.OrganizationID; - await dataService.AddOrUpdateDevice(Org1Device1); ; - Org1Device2.OrganizationID = Org1Admin1.OrganizationID; - await dataService.AddOrUpdateDevice(Org1Device2); + var device1 = new DeviceClientDto() + { + Id = "Org1Device1", + DeviceName = "Org1Device1Name", + OrganizationId = Org1Id + }; + var device2 = new DeviceClientDto() + { + Id = "Org1Device2", + DeviceName = "Org1Device2Name", + OrganizationId = Org1Id + }; + Org1Device1 = (await dataService.AddOrUpdateDevice(device1)).Value; + Org1Device2 = (await dataService.AddOrUpdateDevice(device2)).Value; dataService.AddDeviceGroup(Org1Admin1.OrganizationID, Org1Group1, out _, out _); dataService.AddDeviceGroup(Org1Admin1.OrganizationID, Org1Group2, out _, out _); @@ -158,10 +148,20 @@ namespace Remotely.Tests await dataService.CreateUser("org2testuser2@test.com", false, Org2Admin1.OrganizationID); Org2User2 = dataService.GetUserByNameWithOrg("org2testuser2@test.com"); - Org2Device1.OrganizationID = Org2Admin1.OrganizationID; - await dataService.AddOrUpdateDevice(Org2Device1); ; - Org2Device2.OrganizationID = Org2Admin1.OrganizationID; - await dataService.AddOrUpdateDevice(Org2Device2); + var device3 = new DeviceClientDto() + { + Id = "Org2Device1", + DeviceName = "Org2Device1Name", + OrganizationId = Org2Id + }; + var device4 = new DeviceClientDto() + { + Id = "Org2Device2", + DeviceName = "Org2Device2Name", + OrganizationId = Org2Id + }; + Org2Device1 = (await dataService.AddOrUpdateDevice(device3)).Value; + Org2Device2 = (await dataService.AddOrUpdateDevice(device4)).Value; dataService.AddDeviceGroup(Org2Admin1.OrganizationID, Org2Group1, out _, out _); dataService.AddDeviceGroup(Org2Admin1.OrganizationID, Org2Group2, out _, out _);