From 0f9ea4957b06ddf6b2aa5f05c65a755faaaa9a5d Mon Sep 17 00:00:00 2001 From: Jared Goodwin Date: Tue, 25 Jul 2023 14:05:59 -0700 Subject: [PATCH] Clean up errors and majority of warnings. --- Agent.Installer.Win/Utilities/Logger.cs | 2 +- Server/Auth/ApiAuthorizationFilter.cs | 2 +- Server/Components/AuthComponentBase.cs | 27 ++++- Server/Components/Devices/DeviceCard.razor.cs | 2 +- .../Components/Devices/DevicesFrame.razor.cs | 59 +++++----- Server/Components/Devices/Terminal.razor.cs | 19 +++- Server/Components/Scripts/RunScript.razor.cs | 40 ++++--- .../Components/Scripts/SavedScripts.razor.cs | 34 +++--- .../Components/Scripts/ScriptSchedules.razor | 6 +- .../Scripts/ScriptSchedules.razor.cs | 68 ++++++++---- Server/Components/Scripts/ScriptTreeNode.cs | 4 +- Server/Data/AppDb.cs | 8 +- Server/Hubs/AgentHub.cs | 11 +- Server/Hubs/CircuitConnection.cs | 105 ++++++++++++------ Server/Pages/ApiKeys.razor | 6 +- Server/Pages/Branding.razor | 18 ++- Server/Pages/DeviceDetails.razor | 48 ++++---- Server/Pages/DeviceDetails.razor.cs | 93 +++++++++++----- Server/Pages/Downloads.razor | 24 ++-- Server/Pages/GetSupport.cshtml.cs | 25 +++-- Server/Pages/Invite.cshtml | 7 +- Server/Pages/Invite.cshtml.cs | 16 ++- Server/Pages/ManageOrganization.razor.cs | 25 ++++- Server/Pages/Shared/_Layout.cshtml | 15 ++- Server/Pages/_Host.cshtml | 5 +- Server/Services/CircuitManager.cs | 13 ++- Server/Services/ClientAppState.cs | 8 +- Server/Services/DataService.cs | 23 +++- .../ViewerPageDataProvider.cs | 13 ++- Shared/Models/Device.cs | 2 +- Tests/Server.Tests/DataServiceTests.cs | 72 ++++++------ Tests/Server.Tests/TestData.cs | 48 ++++---- 32 files changed, 543 insertions(+), 305 deletions(-) diff --git a/Agent.Installer.Win/Utilities/Logger.cs b/Agent.Installer.Win/Utilities/Logger.cs index f1e16ce6..e5320dd1 100644 --- a/Agent.Installer.Win/Utilities/Logger.cs +++ b/Agent.Installer.Win/Utilities/Logger.cs @@ -52,7 +52,7 @@ public class Logger while (exception != null) { - File.AppendAllText(LogsPath, $"{DateTimeOffset.Now:yyyy-MM-dd HH:mm:ss.fff}\t[Error]\t{exception?.Message}\t{exception?.StackTrace}\t{exception?.Source}{Environment.NewLine}"); + File.AppendAllText(LogsPath, $"{DateTimeOffset.Now:yyyy-MM-dd HH:mm:ss.fff}\t[Error]\t{exception.Message}\t{exception.StackTrace}\t{exception.Source}{Environment.NewLine}"); Console.WriteLine(exception.Message); exception = exception.InnerException; } diff --git a/Server/Auth/ApiAuthorizationFilter.cs b/Server/Auth/ApiAuthorizationFilter.cs index 8e5916de..3eb306c1 100644 --- a/Server/Auth/ApiAuthorizationFilter.cs +++ b/Server/Auth/ApiAuthorizationFilter.cs @@ -45,7 +45,7 @@ public class ApiAuthorizationFilter : IAsyncAuthorizationFilter if (http.User.Identity?.IsAuthenticated == true) { - var userResult = await _dataService.GetUserByNameWithOrg($"{http.User.Identity.Name}"); + var userResult = await _dataService.GetUserByName($"{http.User.Identity.Name}"); if (userResult.IsSuccess && userResult.Value.IsAdministrator) { http.Request.Headers["OrganizationID"] = userResult.Value.OrganizationID; diff --git a/Server/Components/AuthComponentBase.cs b/Server/Components/AuthComponentBase.cs index c8c1fda8..5666ed96 100644 --- a/Server/Components/AuthComponentBase.cs +++ b/Server/Components/AuthComponentBase.cs @@ -3,26 +3,43 @@ using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Identity; using Remotely.Server.Services; using Remotely.Shared.Models; +using System; +using System.Diagnostics.CodeAnalysis; using System.Threading.Tasks; namespace Remotely.Server.Components; public class AuthComponentBase : ComponentBase { + private RemotelyUser? _user; + private string? _userName; + protected override async Task OnInitializedAsync() { IsAuthenticated = await AuthService.IsAuthenticated(); - User = await AuthService.GetUser(); - Username = User?.UserName; + var userResult = await AuthService.GetUser(); + if (userResult.IsSuccess) + { + _user = userResult.Value; + _userName = userResult.Value.UserName ?? string.Empty; + } await base.OnInitializedAsync(); } public bool IsAuthenticated { get; private set; } - public RemotelyUser User { get; private set; } + public RemotelyUser User + { + get => _user ?? throw new InvalidOperationException("User has not been resolved yet."); + private set => _user = value; + } - public string Username { get; private set; } + public string UserName + { + get => _userName ?? throw new InvalidOperationException("User has not been resolved yet."); + private set => _userName = value; + } [Inject] - protected IAuthService AuthService { get; set; } + protected IAuthService AuthService { get; set; } = null!; } diff --git a/Server/Components/Devices/DeviceCard.razor.cs b/Server/Components/Devices/DeviceCard.razor.cs index 8c41efaf..cfb503fa 100644 --- a/Server/Components/Devices/DeviceCard.razor.cs +++ b/Server/Components/Devices/DeviceCard.razor.cs @@ -80,7 +80,7 @@ public partial class DeviceCard : AuthComponentBase, IDisposable await base.OnInitializedAsync(); _theme = await AppState.GetEffectiveTheme(); _currentVersion = UpgradeService.GetCurrentVersion(); - _deviceGroups = DataService.GetDeviceGroups(Username); + _deviceGroups = DataService.GetDeviceGroups(UserName); AppState.PropertyChanged += AppState_PropertyChanged; CircuitConnection.MessageReceived += CircuitConnection_MessageReceived; } diff --git a/Server/Components/Devices/DevicesFrame.razor.cs b/Server/Components/Devices/DevicesFrame.razor.cs index fd0ac926..3d2cd22f 100644 --- a/Server/Components/Devices/DevicesFrame.razor.cs +++ b/Server/Components/Devices/DevicesFrame.razor.cs @@ -34,29 +34,26 @@ public partial class DevicesFrame : AuthComponentBase, IDisposable private readonly List _sortableProperties = new(); private int _currentPage = 1; private int _devicesPerPage = 25; - private string _filter; + private string? _filter; private bool _hideOfflineDevices = true; - private string _selectedGroupId; + private string? _selectedGroupId; private string _selectedSortProperty = "DeviceName"; private ListSortDirection _sortDirection; [Inject] - private IClientAppState AppState { get; set; } + private IClientAppState AppState { get; init; } = null!; [Inject] - private ICircuitConnection CircuitConnection { get; set; } + private ICircuitConnection CircuitConnection { get; init; } = null!; [Inject] - private IDataService DataService { get; set; } + private IDataService DataService { get; init; } = null!; [Inject] - private IJsInterop JsInterop { get; set; } + private IJsInterop JsInterop { get; init; } = null!; [Inject] - private ILogger Logger { get; set; } - - [Inject] - private IToastService ToastService { get; set; } + private IToastService ToastService { get; init; } = null!; private int TotalPages => (int)Math.Max(1, Math.Ceiling((decimal)_filteredDevices.Count / _devicesPerPage)); @@ -82,7 +79,7 @@ public partial class DevicesFrame : AuthComponentBase, IDisposable _deviceGroups.Clear(); - _deviceGroups.AddRange(DataService.GetDeviceGroups(User.UserName)); + _deviceGroups.AddRange(DataService.GetDeviceGroups(UserName)); _selectedGroupId = _deviceGroupAll; @@ -105,23 +102,31 @@ public partial class DevicesFrame : AuthComponentBase, IDisposable return shouldRender; } - private void AddScriptResult(ScriptResult result) + private async Task AddScriptResult(ScriptResult result) { - var device = DataService.GetDevice(result.DeviceID); - AppState.AddTerminalLine($"{device?.DeviceName} @ {result.TimeStamp}", "font-weight-bold"); + var deviceResult = await DataService.GetDevice(result.DeviceID); + if (!deviceResult.IsSuccess) + { + return; + } - foreach (var line in result.StandardOutput) + AppState.AddTerminalLine($"{deviceResult.Value.DeviceName} @ {result.TimeStamp}", "font-weight-bold"); + + var stdOut = result.StandardOutput ?? Array.Empty(); + var stdErr = result.ErrorOutput ?? Array.Empty(); + + foreach (var line in stdOut) { AppState.AddTerminalLine(line, "text-info"); } - foreach (var line in result.ErrorOutput) + foreach (var line in stdErr) { AppState.AddTerminalLine(line, "text-danger"); } AppState.InvokePropertyChanged(nameof(AppState.TerminalLines)); } - private void AppState_PropertyChanged(object sender, PropertyChangedEventArgs e) + private void AppState_PropertyChanged(object? sender, PropertyChangedEventArgs e) { if (e.PropertyName == nameof(AppState.DevicesFrameFocusedCardState) || e.PropertyName == nameof(AppState.DevicesFrameFocusedDevice) || @@ -131,7 +136,7 @@ public partial class DevicesFrame : AuthComponentBase, IDisposable } } - private void CircuitConnection_MessageReceived(object sender, CircuitEvent args) + private async void CircuitConnection_MessageReceived(object? sender, CircuitEvent args) { switch (args.EventName) { @@ -165,13 +170,15 @@ public partial class DevicesFrame : AuthComponentBase, IDisposable var className = (string)args.Params[2]; AppState.AddTerminalLine(terminalMessage); ToastService.ShowToast(toastMessage, classString: className); - InvokeAsync(StateHasChanged); + await InvokeAsync(StateHasChanged); } break; case CircuitEventName.ScriptResult: { - var result = (ScriptResult)args.Params[0]; - AddScriptResult(result); + if (args.Params[0] is ScriptResult result) + { + await AddScriptResult(result); + } } break; default: @@ -181,7 +188,7 @@ public partial class DevicesFrame : AuthComponentBase, IDisposable private void ClearSelectedCard() { - AppState.DevicesFrameFocusedDevice = null; + AppState.DevicesFrameFocusedDevice = string.Empty; AppState.DevicesFrameFocusedCardState = DeviceCardState.Normal; } @@ -238,8 +245,8 @@ public partial class DevicesFrame : AuthComponentBase, IDisposable var propInfo = _sortableProperties.Find(x => x.Name == _selectedSortProperty); - var valueA = propInfo.GetValue(a); - var valueB = propInfo.GetValue(b); + var valueA = propInfo?.GetValue(a); + var valueB = propInfo?.GetValue(b); return Comparer.Default.Compare(valueA, valueB) * direction; }); @@ -280,7 +287,7 @@ public partial class DevicesFrame : AuthComponentBase, IDisposable { _allDevices.Clear(); - var devices = DataService.GetDevicesForUser(Username) + var devices = DataService.GetDevicesForUser(UserName) .OrderByDescending(x => x.IsOnline) .ToList(); @@ -340,7 +347,7 @@ public partial class DevicesFrame : AuthComponentBase, IDisposable private async Task WakeDevices() { var offlineDevices = DataService - .GetDevicesForUser(Username) + .GetDevicesForUser(UserName) .Where(x => !x.IsOnline); if (_selectedGroupId == _deviceGroupNone) diff --git a/Server/Components/Devices/Terminal.razor.cs b/Server/Components/Devices/Terminal.razor.cs index 82bf98f9..0280b7eb 100644 --- a/Server/Components/Devices/Terminal.razor.cs +++ b/Server/Components/Devices/Terminal.razor.cs @@ -160,12 +160,25 @@ public partial class Terminal : AuthComponentBase, IDisposable AppState.InvokePropertyChanged(nameof(AppState.TerminalLines)); } } - private void DisplayCompletions(List completionMatches) + private async Task DisplayCompletions(List completionMatches) { var deviceId = AppState.DevicesFrameSelectedDevices.FirstOrDefault(); - var device = DataService.GetDevice(deviceId); + if (string.IsNullOrWhiteSpace(deviceId)) + { + return; + } - AppState.AddTerminalLine($"Completions for {device?.DeviceName}", className: "font-weight-bold"); + var deviceResult = await DataService.GetDevice(deviceId); + + if (!deviceResult.IsSuccess) + { + ToastService.ShowToast2(deviceResult.Reason, Enums.ToastType.Warning); + return; + } + + AppState.AddTerminalLine( + $"Completions for {deviceResult.Value.DeviceName}", + className: "font-weight-bold"); foreach (var match in completionMatches) { diff --git a/Server/Components/Scripts/RunScript.razor.cs b/Server/Components/Scripts/RunScript.razor.cs index f5c0ce25..75592689 100644 --- a/Server/Components/Scripts/RunScript.razor.cs +++ b/Server/Components/Scripts/RunScript.razor.cs @@ -31,25 +31,25 @@ public partial class RunScript : AuthComponentBase private bool _runOnNextConnect = true; - private SavedScript _selectedScript; + private SavedScript? _selectedScript; [Inject] - private IDataService DataService { get; set; } + private IDataService DataService { get; init; } = null!; [Inject] - private IJsInterop JsInterop { get; set; } + private IJsInterop JsInterop { get; init; } = null!; [Inject] - private IToastService ToastService { get; set; } + private IToastService ToastService { get; init; } = null!; [Inject] - private IAgentHubSessionCache ServiceSessionCache { get; init; } + private IAgentHubSessionCache ServiceSessionCache { get; init; } = null!; [Inject] - private ICircuitConnection CircuitConnection { get; set; } + private ICircuitConnection CircuitConnection { get; init; } = null!; [CascadingParameter] - private ScriptsPage ParentPage { get; set; } + private ScriptsPage ParentPage { get; init; } = null!; protected override void OnAfterRender(bool firstRender) { @@ -64,16 +64,20 @@ public partial class RunScript : AuthComponentBase { await base.OnInitializedAsync(); - _deviceGroups = DataService.GetDeviceGroups(User.UserName); + _deviceGroups = DataService.GetDeviceGroups(UserName); _devices = DataService - .GetDevicesForUser(User.UserName) + .GetDevicesForUser(UserName) .OrderBy(x => x.DeviceName) .ToArray(); } private void DeviceGroupSelectedChanged(ChangeEventArgs args, DeviceGroup deviceGroup) { - var isSelected = (bool)args.Value; + if (args.Value is not bool isSelected) + { + return; + } + if (isSelected) { _selectedDeviceGroups.Add(deviceGroup.ID); @@ -86,7 +90,11 @@ public partial class RunScript : AuthComponentBase private void DeviceSelectedChanged(ChangeEventArgs args, Device device) { - var isSelected = (bool)args.Value; + if (args.Value is not bool isSelected) + { + return; + } + if (isSelected) { _selectedDevices.Add(device.ID); @@ -113,7 +121,7 @@ public partial class RunScript : AuthComponentBase } var deviceIdsFromDeviceGroups = _devices - .Where(x => _selectedDeviceGroups.Contains(x.DeviceGroupID)) + .Where(x => _selectedDeviceGroups.Contains(x.DeviceGroupID!)) .Select(x => x.ID); var deviceIds = _selectedDevices @@ -121,7 +129,7 @@ public partial class RunScript : AuthComponentBase .Distinct() .ToArray(); - var filteredDevices = DataService.FilterDeviceIDsByUserPermission(deviceIds.ToArray(), User); + var filteredDevices = DataService.FilterDeviceIdsByUserPermission(deviceIds.ToArray(), User); var onlineDevices = ServiceSessionCache.FilterDevicesByOnlineStatus(filteredDevices, true); @@ -157,7 +165,11 @@ public partial class RunScript : AuthComponentBase { if (viewModel.Script is not null) { - _selectedScript = await DataService.GetSavedScript(User.Id, viewModel.Script.Id); + var scriptResult = await DataService.GetSavedScript(User.Id, viewModel.Script.Id); + if (scriptResult.IsSuccess) + { + _selectedScript = scriptResult.Value; + } } else { diff --git a/Server/Components/Scripts/SavedScripts.razor.cs b/Server/Components/Scripts/SavedScripts.razor.cs index 17b5754b..a9e4b5e0 100644 --- a/Server/Components/Scripts/SavedScripts.razor.cs +++ b/Server/Components/Scripts/SavedScripts.razor.cs @@ -17,24 +17,24 @@ namespace Remotely.Server.Components.Scripts; public partial class SavedScripts : AuthComponentBase { [CascadingParameter] - private ScriptsPage ParentPage { get; set; } + private ScriptsPage ParentPage { get; set; } = null!; private SavedScript _selectedScript = new() { Name = "Test Script" }; - private string _alertMessage; - private string _alertOptionsShowClass; - private string _environmentVarsShowClass; + private string _alertMessage = string.Empty; + private string _alertOptionsShowClass = string.Empty; + private string _environmentVarsShowClass = string.Empty; [Inject] - public IDataService DataService { get; set; } + public IDataService DataService { get; set; } = null!; [Inject] - public IToastService ToastService { get; set; } + public IToastService ToastService { get; set; } = null!; [Inject] - public IJsInterop JsInterop { get; set; } + public IJsInterop JsInterop { get; set; } = null!; [Inject] - public IModalService ModalService { get; set; } + public IModalService ModalService { get; set; } = null!; private bool CanModifyScript => _selectedScript.Id == Guid.Empty || _selectedScript.CreatorId == User.Id || User.IsAdministrator; @@ -104,18 +104,18 @@ public partial class SavedScripts : AuthComponentBase { if (viewModel.Script is not null) { - _selectedScript = await DataService.GetSavedScript(User.Id, viewModel.Script.Id) ?? new() + var result = await DataService.GetSavedScript(User.Id, viewModel.Script.Id); + if (result.IsSuccess) { - Name = "Test Script" - }; + _selectedScript = result.Value; + return; + } } - else + + _selectedScript = new() { - _selectedScript = new() - { - Name = "Test Script" - }; - } + Name = string.Empty + }; } private void ToggleEnvironmentVarsShown() diff --git a/Server/Components/Scripts/ScriptSchedules.razor b/Server/Components/Scripts/ScriptSchedules.razor index db84391c..fd5e727d 100644 --- a/Server/Components/Scripts/ScriptSchedules.razor +++ b/Server/Components/Scripts/ScriptSchedules.razor @@ -13,12 +13,12 @@
- +
- @@ -26,7 +26,7 @@ New diff --git a/Server/Components/Scripts/ScriptSchedules.razor.cs b/Server/Components/Scripts/ScriptSchedules.razor.cs index a9fd5af5..12dfc9e6 100644 --- a/Server/Components/Scripts/ScriptSchedules.razor.cs +++ b/Server/Components/Scripts/ScriptSchedules.razor.cs @@ -21,13 +21,13 @@ public partial class ScriptSchedules : AuthComponentBase private readonly List _schedules = new(); - private string _alertMessage; + private string _alertMessage = string.Empty; private DeviceGroup[] _deviceGroups = Array.Empty(); private Device[] _devices = Array.Empty(); - private SavedScript _selectedScript; + private SavedScript? _selectedScript; private ScriptSchedule _selectedSchedule = new() { @@ -36,33 +36,37 @@ public partial class ScriptSchedules : AuthComponentBase }; [CascadingParameter] - private ScriptsPage ParentPage { get; set; } + private ScriptsPage ParentPage { get; set; } = null!; [Inject] - private IDataService DataService { get; set; } + private IDataService DataService { get; set; } = null!; [Inject] - private IJsInterop JsInterop { get; set; } + private IJsInterop JsInterop { get; set; } = null!; [Inject] - private IToastService ToastService { get; set; } + private IToastService ToastService { get; set; } = null!; - private bool CanModifyScript => string.IsNullOrWhiteSpace(_selectedSchedule.CreatorId) || - _selectedSchedule.CreatorId == User.Id || - User.IsAdministrator; + private bool CanModifySchedule => + _selectedSchedule.CreatorId == User?.Id || + User?.IsAdministrator == true; - private bool CanDeleteScript => !string.IsNullOrWhiteSpace(_selectedSchedule.CreatorId) && - (_selectedSchedule.CreatorId == User.Id || User.IsAdministrator); + private bool CanDeleteSchedule => + _selectedSchedule.CreatorId == User?.Id || + User?.IsAdministrator == true; protected override async Task OnInitializedAsync() { await base.OnInitializedAsync(); - _deviceGroups = DataService.GetDeviceGroups(User.UserName); - _devices = DataService - .GetDevicesForUser(User.UserName) - .OrderBy(x => x.DeviceName) - .ToArray(); + if (IsAuthenticated) + { + _deviceGroups = DataService.GetDeviceGroups(UserName); + _devices = DataService + .GetDevicesForUser(UserName) + .OrderBy(x => x.DeviceName) + .ToArray(); + } await RefreshSchedules(); } @@ -84,7 +88,7 @@ public partial class ScriptSchedules : AuthComponentBase private async Task DeleteSelectedSchedule() { - if (User.Id != _selectedSchedule.CreatorId) + if (User?.Id != _selectedSchedule.CreatorId) { ToastService.ShowToast("You can't delete other people's script schedules.", classString: "bg-warning"); return; @@ -104,7 +108,10 @@ public partial class ScriptSchedules : AuthComponentBase private void DeviceGroupSelectedChanged(ChangeEventArgs args, DeviceGroup deviceGroup) { - var isSelected = (bool)args.Value; + if (args.Value is not bool isSelected) + { + return; + } if (isSelected) { _selectedDeviceGroups.Add(deviceGroup.ID); @@ -117,7 +124,10 @@ public partial class ScriptSchedules : AuthComponentBase private void DeviceSelectedChanged(ChangeEventArgs args, Device device) { - var isSelected = (bool)args.Value; + if (args.Value is not bool isSelected) + { + return; + } if (isSelected) { _selectedDevices.Add(device.ID); @@ -141,7 +151,7 @@ public partial class ScriptSchedules : AuthComponentBase return; } - if (!CanModifyScript) + if (!CanModifySchedule) { ToastService.ShowToast("You can't modify other people's schedules.", classString: "bg-warning"); return; @@ -177,7 +187,10 @@ public partial class ScriptSchedules : AuthComponentBase private async Task RefreshSchedules() { _schedules.Clear(); - _schedules.AddRange(await DataService.GetScriptSchedules(User.OrganizationID)); + if (User is not null) + { + _schedules.AddRange(await DataService.GetScriptSchedules(User.OrganizationID)); + } } private string GetTableRowClass(ScriptSchedule schedule) @@ -203,14 +216,23 @@ public partial class ScriptSchedules : AuthComponentBase { _selectedDeviceGroups.AddRange(schedule.DeviceGroups.Select(x => x.ID)); } - _selectedScript = await DataService.GetSavedScript(_selectedSchedule.SavedScriptId); + + var result = await DataService.GetSavedScript(_selectedSchedule.SavedScriptId); + if (result.IsSuccess) + { + _selectedScript = result.Value; + } } private async Task ScriptSelected(ScriptTreeNode viewModel) { if (viewModel.Script is not null) { - _selectedScript = await DataService.GetSavedScript(User.Id, viewModel.Script.Id); + var result = await DataService.GetSavedScript(User.Id, viewModel.Script.Id); + if (result.IsSuccess) + { + _selectedScript = result.Value; + } } else diff --git a/Server/Components/Scripts/ScriptTreeNode.cs b/Server/Components/Scripts/ScriptTreeNode.cs index ce683acc..e3d9e76a 100644 --- a/Server/Components/Scripts/ScriptTreeNode.cs +++ b/Server/Components/Scripts/ScriptTreeNode.cs @@ -11,8 +11,8 @@ public class ScriptTreeNode { public string Id { get; } = Guid.NewGuid().ToString(); public TreeItemType ItemType { get; set; } - public string Name { get; init; } + public string Name { get; init; } = string.Empty; public ScriptTreeNode? ParentNode { get; set; } public List ChildItems { get; } = new(); - public SavedScript Script { get; init; } + public SavedScript? Script { get; init; } } diff --git a/Server/Data/AppDb.cs b/Server/Data/AppDb.cs index 6e9d07dd..9a3deff4 100644 --- a/Server/Data/AppDb.cs +++ b/Server/Data/AppDb.cs @@ -135,6 +135,10 @@ public class AppDb : IdentityDbContext builder.Entity() .HasMany(x => x.ScriptSchedules) .WithMany(x => x.Devices); + builder.Entity() + .HasOne(x => x.DeviceGroup) + .WithMany(x => x.Devices) + .IsRequired(false); builder.Entity() .Property(x => x.MacAddresses) .HasConversion( @@ -143,7 +147,9 @@ public class AppDb : IdentityDbContext valueComparer: _stringArrayComparer); builder.Entity() - .HasMany(x => x.Devices); + .HasMany(x => x.Devices) + .WithOne(x => x.DeviceGroup) + .IsRequired(false); builder.Entity() .HasMany(x => x.ScriptSchedules) .WithMany(x => x.DeviceGroups); diff --git a/Server/Hubs/AgentHub.cs b/Server/Hubs/AgentHub.cs index a881d569..811620c3 100644 --- a/Server/Hubs/AgentHub.cs +++ b/Server/Hubs/AgentHub.cs @@ -255,10 +255,15 @@ public class AgentHub : Hub return _circuitManager.InvokeOnConnection(senderConnectionId, CircuitEventName.PowerShellCompletions, completion, intent); } - public Task ScriptResult(string scriptResultId) + public async Task ScriptResult(string scriptResultId) { - var result = _dataService.GetScriptResult(scriptResultId); - return _circuitManager.InvokeOnConnection(result.SenderConnectionID, + var result = await _dataService.GetScriptResult(scriptResultId); + if (!result.IsSuccess) + { + return; + } + + _ = await _circuitManager.InvokeOnConnection($"{result.Value.SenderConnectionID}", CircuitEventName.ScriptResult, result); } diff --git a/Server/Hubs/CircuitConnection.cs b/Server/Hubs/CircuitConnection.cs index 4d452c88..bde56c2b 100644 --- a/Server/Hubs/CircuitConnection.cs +++ b/Server/Hubs/CircuitConnection.cs @@ -27,8 +27,8 @@ namespace Remotely.Server.Hubs; public interface ICircuitConnection { - event EventHandler MessageReceived; - RemotelyUser User { get; } + event EventHandler? MessageReceived; + RemotelyUser? User { get; } Task DeleteRemoteLogs(string deviceId); @@ -85,6 +85,8 @@ public class CircuitConnection : CircuitHandler, ICircuitConnection private readonly ILogger _logger; private readonly IAgentHubSessionCache _agentSessionCache; private readonly IToastService _toastService; + private RemotelyUser? _user; + public CircuitConnection( IAuthService authService, IDataService dataService, @@ -112,10 +114,15 @@ public class CircuitConnection : CircuitHandler, ICircuitConnection } - public event EventHandler MessageReceived; + public event EventHandler? MessageReceived; - public string ConnectionId { get; set; } - public RemotelyUser User { get; internal set; } + public string ConnectionId { get; } = Guid.NewGuid().ToString(); + + public RemotelyUser User + { + get => _user ?? throw new InvalidOperationException("User has not been resolved yet."); + internal set => _user = value; + } public Task DeleteRemoteLogs(string deviceId) @@ -129,14 +136,14 @@ public class CircuitConnection : CircuitHandler, ICircuitConnection _logger.LogInformation("Delete logs command sent. Device: {deviceId}. User: {username}", deviceId, - User.UserName); + User?.UserName); return _agentHubContext.Clients.Client(key).SendAsync("DeleteLogs"); } public Task ExecuteCommandOnAgent(ScriptingShell shell, string command, string[] deviceIDs) { - deviceIDs = _dataService.FilterDeviceIDsByUserPermission(deviceIDs, User); + deviceIDs = _dataService.FilterDeviceIdsByUserPermission(deviceIDs, User); var connections = GetActiveConnectionsForUserOrg(deviceIDs); _logger.LogInformation("Command executed by {username}. Shell: {shell}. Command: {command}. Devices: {deviceIds}", @@ -162,7 +169,13 @@ public class CircuitConnection : CircuitHandler, ICircuitConnection public Task GetPowerShellCompletions(string inputText, int currentIndex, CompletionIntent intent, bool? forward) { - var (canAccess, key) = CanAccessDevice(_appState.DevicesFrameSelectedDevices.FirstOrDefault()); + var device = _appState.DevicesFrameSelectedDevices.FirstOrDefault(); + if (device is null) + { + return Task.CompletedTask; + } + + var (canAccess, key) = CanAccessDevice(device); if (!canAccess) { return Task.CompletedTask; @@ -202,8 +215,13 @@ public class CircuitConnection : CircuitHandler, ICircuitConnection { if (await _authService.IsAuthenticated()) { - User = await _authService.GetUser(); - ConnectionId = Guid.NewGuid().ToString(); + var userResult = await _authService.GetUser(); + if (!userResult.IsSuccess) + { + _toastService.ShowToast2("Authorization failure.", Enums.ToastType.Error); + return; + } + _user = userResult.Value; _circuitManager.TryAddConnection(ConnectionId, this); } await base.OnCircuitOpenedAsync(circuit, cancellationToken); @@ -211,7 +229,7 @@ public class CircuitConnection : CircuitHandler, ICircuitConnection public Task ReinstallAgents(string[] deviceIDs) { - deviceIDs = _dataService.FilterDeviceIDsByUserPermission(deviceIDs, User); + deviceIDs = _dataService.FilterDeviceIdsByUserPermission(deviceIDs, User); var connections = GetActiveConnectionsForUserOrg(deviceIDs); foreach (var connection in connections) { @@ -283,12 +301,20 @@ public class CircuitConnection : CircuitHandler, ICircuitConnection _remoteControlSessionCache.AddOrUpdate($"{sessionId}", session); - var organization = _dataService.GetOrganizationNameByUserName(User.UserName); + var orgResult = await _dataService.GetOrganizationNameByUserName($"{User.UserName}"); + + if (!orgResult.IsSuccess) + { + _toastService.ShowToast2(orgResult.Reason, Enums.ToastType.Warning); + return Result.Fail(orgResult.Reason); + } + + var organization = _dataService.GetOrganizationNameByUserName($"{User.UserName}"); await _agentHubContext.Clients.Client(serviceConnectionId).SendAsync("RemoteControl", sessionId, accessKey, ConnectionId, - User.UserOptions.DisplayName, + User.UserOptions?.DisplayName, organization, User.OrganizationID); @@ -297,22 +323,31 @@ public class CircuitConnection : CircuitHandler, ICircuitConnection public Task RemoveDevices(string[] deviceIDs) { - var filterDevices = _dataService.FilterDeviceIDsByUserPermission(deviceIDs, User); - _dataService.RemoveDevices(filterDevices); + if (User is not null) + { + var filterDevices = _dataService.FilterDeviceIdsByUserPermission(deviceIDs, User); + _dataService.RemoveDevices(filterDevices); + } + return Task.CompletedTask; } - public async Task RunScript(IEnumerable deviceIds, Guid savedScriptId, int scriptRunId, ScriptInputType scriptInputType, bool runAsHostedService) + public async Task RunScript( + IEnumerable deviceIds, + Guid savedScriptId, + int scriptRunId, + ScriptInputType scriptInputType, + bool runAsHostedService) { - string username; + var username = string.Empty; if (runAsHostedService) { username = "Remotely Server"; } - else + else if (User is not null) { username = User.UserName; - deviceIds = _dataService.FilterDeviceIDsByUserPermission(deviceIds.ToArray(), User); + deviceIds = _dataService.FilterDeviceIdsByUserPermission(deviceIds.ToArray(), User); } var authToken = _expiringTokenService.GetToken(Time.Now.AddMinutes(AppConstants.ScriptRunExpirationMinutes)); @@ -326,32 +361,37 @@ public class CircuitConnection : CircuitHandler, ICircuitConnection } - public Task SendChat(string message, string deviceId) + public async Task SendChat(string message, string deviceId) { if (!_dataService.DoesUserHaveAccessToDevice(deviceId, User)) { - return Task.CompletedTask; + return; } if (!_agentSessionCache.TryGetByDeviceId(deviceId, out var device) || !_agentSessionCache.TryGetConnectionId(deviceId, out var connectionId)) { _toastService.ShowToast("Device not found."); - return Task.CompletedTask; + return; } if (device.OrganizationID != User.OrganizationID) { _toastService.ShowToast("Unauthorized."); - return Task.CompletedTask; + return; } - var organizationName = _dataService.GetOrganizationNameByUserName(User.UserName); + var orgResult = await _dataService.GetOrganizationNameByUserName($"{User.UserName}"); + if (!orgResult.IsSuccess) + { + _toastService.ShowToast2("Organization not found.", Enums.ToastType.Warning); + return; + } - return _agentHubContext.Clients.Client(connectionId).SendAsync("Chat", - User.UserOptions.DisplayName ?? User.UserName, + await _agentHubContext.Clients.Client(connectionId).SendAsync("Chat", + User.UserOptions?.DisplayName ?? User.UserName, message, - organizationName, + orgResult.Value, User.OrganizationID, false, ConnectionId); @@ -397,16 +437,15 @@ public class CircuitConnection : CircuitHandler, ICircuitConnection await _agentHubContext.Clients.Client(connectionId).SendAsync("TriggerHeartbeat"); } - public Task UninstallAgents(string[] deviceIDs) + public async Task UninstallAgents(string[] deviceIDs) { - deviceIDs = _dataService.FilterDeviceIDsByUserPermission(deviceIDs, User); + deviceIDs = _dataService.FilterDeviceIdsByUserPermission(deviceIDs, User); var connections = GetActiveConnectionsForUserOrg(deviceIDs); foreach (var connection in connections) { - _agentHubContext.Clients.Client(connection).SendAsync("UninstallAgent"); + await _agentHubContext.Clients.Client(connection).SendAsync("UninstallAgent"); } _dataService.RemoveDevices(deviceIDs); - return Task.CompletedTask; } public Task UpdateTags(string deviceID, string tags) @@ -436,7 +475,7 @@ public class CircuitConnection : CircuitHandler, ICircuitConnection User.UserName, string.Join(", ", fileIDs)); - deviceIDs = _dataService.FilterDeviceIDsByUserPermission(deviceIDs, User); + deviceIDs = _dataService.FilterDeviceIdsByUserPermission(deviceIDs, User); var connections = GetActiveConnectionsForUserOrg(deviceIDs); foreach (var connection in connections) { @@ -477,7 +516,7 @@ public class CircuitConnection : CircuitHandler, ICircuitConnection try { var deviceIds = devices.Select(x => x.ID).ToArray(); - var filteredIds = _dataService.FilterDeviceIDsByUserPermission(deviceIds, User); + var filteredIds = _dataService.FilterDeviceIdsByUserPermission(deviceIds, User); var filteredDevices = devices.Where(x => filteredIds.Contains(x.ID)).ToArray(); var availableDevices = _agentSessionCache diff --git a/Server/Pages/ApiKeys.razor b/Server/Pages/ApiKeys.razor index 2938ebba..2386ad50 100644 --- a/Server/Pages/ApiKeys.razor +++ b/Server/Pages/ApiKeys.razor @@ -93,7 +93,7 @@ else var secret = RandomGenerator.GenerateString(36); var secretHash = new PasswordHasher().HashPassword(string.Empty, secret); - var result = await DataService.CreateApiToken(Username, _createKeyName, secretHash); + var result = await DataService.CreateApiToken(UserName, _createKeyName, secretHash); if (!result.IsSuccess) { ToastService.ShowToast2(result.Reason, ToastType.Error); @@ -112,7 +112,7 @@ else return; } - var deleteResult = await DataService.DeleteApiToken(Username, keyId); + var deleteResult = await DataService.DeleteApiToken(UserName, keyId); if (!deleteResult.IsSuccess) { ToastService.ShowToast2(deleteResult.Reason, ToastType.Error); @@ -137,7 +137,7 @@ else var newName = await JsInterop.Prompt("New key name"); if (!string.IsNullOrWhiteSpace(newName)) { - await DataService.RenameApiToken(Username, keyId, newName); + await DataService.RenameApiToken(UserName, keyId, newName); RefreshData(); _alertMessage = "Key renamed."; } diff --git a/Server/Pages/Branding.razor b/Server/Pages/Branding.razor index ac747c9c..2b9a26f7 100644 --- a/Server/Pages/Branding.razor +++ b/Server/Pages/Branding.razor @@ -129,14 +129,26 @@ private async Task LoadBrandingInfo() { - var organization = await DataService.GetOrganizationByUserName(User.UserName); + var orgResult = await DataService.GetOrganizationByUserName($"{UserName}"); - var brandingInfo = await DataService.GetBrandingInfo(organization.ID); + if (!orgResult.IsSuccess) + { + ToastService.ShowToast2(orgResult.Reason, ToastType.Warning); + return; + } + var brandingResult= await DataService.GetBrandingInfo(orgResult.Value.ID); + + if (!brandingResult.IsSuccess) + { + ToastService.ShowToast2(brandingResult.Reason, ToastType.Warning); + return; + } + var brandingInfo = brandingResult.Value; _inputModel.ProductName = brandingInfo.Product; - if (brandingInfo?.Icon?.Any() == true) + if (brandingResult.Value?.Icon?.Any() == true) { _base64Icon = Convert.ToBase64String(brandingInfo.Icon); } diff --git a/Server/Pages/DeviceDetails.razor b/Server/Pages/DeviceDetails.razor index b52a521c..f8979bc2 100644 --- a/Server/Pages/DeviceDetails.razor +++ b/Server/Pages/DeviceDetails.razor @@ -29,11 +29,11 @@
} -else if (Device is null) +else if (_device is null) {

Device not found.

} -else if (!DataService.DoesUserHaveAccessToDevice(Device.ID, User)) +else if (!DataService.DoesUserHaveAccessToDevice(_device.ID, User)) {

Unauthorized.

} @@ -59,7 +59,7 @@ else Device Details - + @@ -72,31 +72,31 @@ else
- +
- +
- +
- +
- +
@@ -107,7 +107,7 @@ else
- +
@@ -115,7 +115,7 @@ else Total Storage:
- +
@@ -123,7 +123,7 @@ else Memory:
- +
@@ -131,7 +131,7 @@ else Total Memory:
- +
@@ -139,7 +139,7 @@ else Public IP:
- +
@@ -152,42 +152,42 @@ else class="form-control" name="agent-memory-total" readonly - value="@(string.Join(", ", Device.MacAddresses ?? Array.Empty()))" /> + value="@(string.Join(", ", _device.MacAddresses ?? Array.Empty()))" />
- - + +
- + - @foreach (var group in DataService.GetDeviceGroups(Username)) + @foreach (var group in DataService.GetDeviceGroups(UserName)) { } - +
- - + +
- - + +
@@ -199,7 +199,7 @@ else
- @if (!Device.IsOnline) + @if (!_device.IsOnline) {
Device must be online to retrieve logs.
} diff --git a/Server/Pages/DeviceDetails.razor.cs b/Server/Pages/DeviceDetails.razor.cs index 5f9cc4aa..830fe90c 100644 --- a/Server/Pages/DeviceDetails.razor.cs +++ b/Server/Pages/DeviceDetails.razor.cs @@ -20,33 +20,34 @@ public partial class DeviceDetails : AuthComponentBase private readonly ConcurrentQueue _logLines = new(); private readonly ConcurrentQueue _scriptResults = new(); - private string _alertMessage; - private string _inputDeviceId; + private string? _alertMessage; + private Device? _device; + private string? _inputDeviceId; [Parameter] - public string ActiveTab { get; set; } + public string ActiveTab { get; set; } = string.Empty; [Parameter] - public string DeviceId { get; set; } - [Inject] - private ICircuitConnection CircuitConnection { get; set; } + public string DeviceId { get; set; } = string.Empty; [Inject] - private IDataService DataService { get; set; } - - private Device Device { get; set; } + private ICircuitConnection CircuitConnection { get; set; } = null!; [Inject] - private IJsInterop JsInterop { get; set; } + private IDataService DataService { get; set; } = null!; + [Inject] - private IModalService ModalService { get; set; } + private IJsInterop JsInterop { get; set; } = null!; [Inject] - private NavigationManager NavManager { get; set; } + private IModalService ModalService { get; set; } = null!; [Inject] - private IToastService ToastService { get; set; } + private NavigationManager NavManager { get; set; } = null!; + + [Inject] + private IToastService ToastService { get; set; } = null!; protected override async Task OnInitializedAsync() @@ -55,13 +56,21 @@ public partial class DeviceDetails : AuthComponentBase if (!string.IsNullOrWhiteSpace(DeviceId)) { - Device = DataService.GetDevice(DeviceId); + var deviceResult = await DataService.GetDevice(DeviceId); + if (deviceResult.IsSuccess) + { + _device = deviceResult.Value; + } + else + { + ToastService.ShowToast2(deviceResult.Reason, Enums.ToastType.Warning); + } } CircuitConnection.MessageReceived += CircuitConnection_MessageReceived; } - private void CircuitConnection_MessageReceived(object sender, Models.CircuitEvent e) + private void CircuitConnection_MessageReceived(object? sender, Models.CircuitEvent e) { if (e.EventName == Models.CircuitEventName.RemoteLogsReceived) { @@ -73,10 +82,15 @@ public partial class DeviceDetails : AuthComponentBase private async Task DeleteLogs() { + if (_device is null) + { + return; + } + var result = await JsInterop.Confirm("Are you sure you want to delete the remote logs?"); if (result) { - await CircuitConnection.DeleteRemoteLogs(Device.ID); + await CircuitConnection.DeleteRemoteLogs(_device.ID); ToastService.ShowToast("Delete command sent."); } } @@ -96,22 +110,32 @@ public partial class DeviceDetails : AuthComponentBase private void GetRemoteLogs() { + if (_device is null) + { + return; + } + _logLines.Clear(); - if (Device.IsOnline) + if (_device.IsOnline) { - CircuitConnection.GetRemoteLogs(Device.ID); + CircuitConnection.GetRemoteLogs(_device.ID); } } private void GetScriptHistory() { + if (_device is null) + { + return; + } + _scriptResults.Clear(); if (User.IsAdministrator) { var results = DataService - .GetAllScriptResults(User.OrganizationID, Device.ID) + .GetAllScriptResults(User.OrganizationID, _device.ID) .OrderByDescending(x => x.TimeStamp); foreach (var result in results) @@ -122,7 +146,7 @@ public partial class DeviceDetails : AuthComponentBase else { var results = DataService - .GetAllCommandResultsForUser(User.OrganizationID, User.UserName, Device.ID) + .GetAllCommandResultsForUser(User.OrganizationID, UserName, _device.ID) .OrderByDescending(x => x.TimeStamp); foreach (var result in results) @@ -154,11 +178,17 @@ public partial class DeviceDetails : AuthComponentBase private Task HandleValidSubmit() { - DataService.UpdateDevice(Device.ID, - Device.Tags, - Device.Alias, - Device.DeviceGroupID, - Device.Notes); + if (_device is null) + { + return Task.CompletedTask; + } + + DataService.UpdateDevice( + _device.ID, + _device.Tags, + _device.Alias, + _device.DeviceGroupID, + _device.Notes); _alertMessage = "Device details saved."; ToastService.ShowToast("Device details saved."); @@ -173,20 +203,25 @@ public partial class DeviceDetails : AuthComponentBase private void ShowAllDisks() { - var disksString = JsonSerializer.Serialize(Device.Drives, JsonSerializerHelper.IndentedOptions); + if (_device is null) + { + return; + } + + var disksString = JsonSerializer.Serialize(_device.Drives, JsonSerializerHelper.IndentedOptions); void modalBody(RenderTreeBuilder builder) { builder.AddMarkupContent(0, $"
{disksString}
"); } - ModalService.ShowModal($"All Disks for {Device.DeviceName}", modalBody); + ModalService.ShowModal($"All Disks for {_device.DeviceName}", modalBody); } private void ShowFullScriptOutput(ScriptResult result) { void outputModal(RenderTreeBuilder builder) { - var output = string.Join("\r\n", result.StandardOutput); - var error = string.Join("\r\n", result.ErrorOutput); + var output = string.Join("\r\n", $"{result.StandardOutput}"); + var error = string.Join("\r\n", $"{result.ErrorOutput}"); var textareaStyle = "width: 100%; height: 200px; white-space: pre;"; builder.AddMarkupContent(0, "
Input
"); diff --git a/Server/Pages/Downloads.razor b/Server/Pages/Downloads.razor index 51cebfd0..a48d3e12 100644 --- a/Server/Pages/Downloads.razor +++ b/Server/Pages/Downloads.razor @@ -2,7 +2,7 @@ @using Microsoft.AspNetCore.Hosting @using Microsoft.Extensions.Logging -@inject AuthenticationStateProvider AuthProvider +@inject IAuthService Auth @inject IDataService DataService @inject UserManager UserManager @inject IWebHostEnvironment HostEnv @@ -174,24 +174,30 @@
@code { - private string _organizationId; + private string? _organizationId; private bool _isAuthenticated; protected override async Task OnInitializedAsync() { - await base.OnInitializedAsync(); - - var authState = await AuthProvider.GetAuthenticationStateAsync(); - _isAuthenticated = authState.User.Identity.IsAuthenticated; + _isAuthenticated = await Auth.IsAuthenticated(); if (_isAuthenticated) { - var currentUser = await DataService.GetUserByName(authState.User.Identity.Name); - _organizationId = currentUser.OrganizationID; + var userResult = await Auth.GetUser(); + if (userResult.IsSuccess) + { + _organizationId = userResult.Value.OrganizationID; + } } else { - _organizationId = (await DataService.GetDefaultOrganization())?.ID; + var orgResult = await DataService.GetDefaultOrganization(); + if (orgResult.IsSuccess) + { + _organizationId = orgResult.Value.ID; + } } + + await base.OnInitializedAsync(); } } \ No newline at end of file diff --git a/Server/Pages/GetSupport.cshtml.cs b/Server/Pages/GetSupport.cshtml.cs index 8233b5c0..216eb041 100644 --- a/Server/Pages/GetSupport.cshtml.cs +++ b/Server/Pages/GetSupport.cshtml.cs @@ -18,7 +18,7 @@ public class GetSupportModel : PageModel } [TempData] - public string StatusMessage { get; set; } + public string? StatusMessage { get; set; } [BindProperty] public InputModel Input { get; set; } @@ -35,8 +35,15 @@ public class GetSupportModel : PageModel return Page(); } - var orgID = _dataService.GetDevice(deviceId)?.OrganizationID; + var deviceResult = await _dataService.GetDevice(deviceId); + if (!deviceResult.IsSuccess) + { + StatusMessage = "Device not found."; + return Page(); + } + var orgId = deviceResult.Value.OrganizationID; + var alertParts = new string[] { $"{Input.Name} is requesting support.", @@ -47,12 +54,16 @@ public class GetSupportModel : PageModel }; var alertMessage = string.Join(" ", alertParts); - await _dataService.AddAlert(deviceId, orgID, alertMessage); + await _dataService.AddAlert(deviceId, orgId, alertMessage); - var orgUsers = await _dataService.GetAllUsersInOrganization(orgID); + var orgUsers = await _dataService.GetAllUsersInOrganization(orgId); var emailMessage = string.Join("
", alertParts); foreach (var user in orgUsers) { + if (string.IsNullOrWhiteSpace(user.Email)) + { + continue; + } await _emailSender.SendEmailAsync(user.Email, "Support Request", emailMessage); } @@ -65,9 +76,9 @@ public class GetSupportModel : PageModel { [StringLength(150)] [Required] - public string Name { get; set; } - public string Email { get; set; } - public string Phone { get; set; } + public required string Name { get; set; } + public string? Email { get; set; } + public string? Phone { get; set; } public bool ChatResponseOk { get; set; } } } \ No newline at end of file diff --git a/Server/Pages/Invite.cshtml b/Server/Pages/Invite.cshtml index 002979e1..aa500e0a 100644 --- a/Server/Pages/Invite.cshtml +++ b/Server/Pages/Invite.cshtml @@ -14,7 +14,12 @@ You've successfully joined the organization!

} - + else if (string.IsNullOrWhiteSpace(Model.Input.InviteID)) + { +
+ Invitation ID is missing from the request. +
+ } else {
diff --git a/Server/Pages/Invite.cshtml.cs b/Server/Pages/Invite.cshtml.cs index 1d53afb3..6ce34c38 100644 --- a/Server/Pages/Invite.cshtml.cs +++ b/Server/Pages/Invite.cshtml.cs @@ -2,22 +2,25 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using Remotely.Server.Services; +using System.Threading.Tasks; namespace Remotely.Server.Pages; [Authorize] public class InviteModel : PageModel { + private readonly IDataService _dataService; + public InviteModel(IDataService dataService) { - DataService = dataService; + _dataService = dataService; } - private IDataService DataService { get; } + public bool Success { get; set; } public class InputModel { - public string InviteID { get; set; } + public string? InviteID { get; set; } } [BindProperty] @@ -28,12 +31,13 @@ public class InviteModel : PageModel if (string.IsNullOrWhiteSpace(id)) { ModelState.AddModelError("MissingID", "No invititation ID is specified."); + return; } Input.InviteID = id; } - public IActionResult OnPost() + public async Task OnPost() { if (string.IsNullOrWhiteSpace(Input?.InviteID)) { @@ -42,8 +46,8 @@ public class InviteModel : PageModel return Page(); } - var result = DataService.JoinViaInvitation(User.Identity.Name, Input.InviteID); - if (result == false) + var result = await _dataService.JoinViaInvitation($"{User.Identity?.Name}", Input.InviteID); + if (!result.IsSuccess) { Success = false; ModelState.AddModelError("InviteIDNotFound", "The invitation ID wasn't found or is for another account."); diff --git a/Server/Pages/ManageOrganization.razor.cs b/Server/Pages/ManageOrganization.razor.cs index c43efbc2..992813a7 100644 --- a/Server/Pages/ManageOrganization.razor.cs +++ b/Server/Pages/ManageOrganization.razor.cs @@ -120,7 +120,7 @@ public partial class ManageOrganization : AuthComponentBase return; } - DataService.DeleteInvite(User.OrganizationID, invite.ID); + await DataService.DeleteInvite(User.OrganizationID, invite.ID); _invites.RemoveAll(x => x.ID == invite.ID); ToastService.ShowToast("Invitation deleted."); } @@ -143,7 +143,7 @@ public partial class ManageOrganization : AuthComponentBase return; } - DataService.DeleteDeviceGroup(User.OrganizationID, _selectedDeviceGroupId); + await DataService.DeleteDeviceGroup(User.OrganizationID, _selectedDeviceGroupId); _deviceGroups.RemoveAll(x => x.ID == _selectedDeviceGroupId); _selectedDeviceGroupId = string.Empty; } @@ -237,14 +237,20 @@ public partial class ManageOrganization : AuthComponentBase private async Task RefreshData() { - _organization = await DataService.GetOrganizationByUserName(Username); + var orgResult = await DataService.GetOrganizationByUserName(UserName); + if (!orgResult.IsSuccess) + { + ToastService.ShowToast2(orgResult.Reason, Enums.ToastType.Warning); + return; + } + _organization = orgResult.Value; _orgUsers.Clear(); _invites.Clear(); _deviceGroups.Clear(); _invites.AddRange(DataService.GetAllInviteLinks(User.OrganizationID).OrderBy(x => x.InvitedUser)); - _deviceGroups.AddRange(DataService.GetDeviceGroups(Username).OrderBy(x => x.Name)); + _deviceGroups.AddRange(DataService.GetDeviceGroups(UserName).OrderBy(x => x.Name)); var orgUsers = await DataService.GetAllUsersInOrganization(User.OrganizationID); _orgUsers.AddRange(orgUsers.OrderBy(x => x.UserName)); } @@ -277,9 +283,16 @@ public partial class ManageOrganization : AuthComponentBase if (!DataService.DoesUserExist(_inviteEmail)) { var result = await DataService.CreateUser(_inviteEmail, _inviteAsAdmin, User.OrganizationID); - if (result) + if (result.IsSuccess) { - var user = await DataService.GetUserByName(_inviteEmail); + var userResult = await DataService.GetUserByName(_inviteEmail); + if (!userResult.IsSuccess) + { + ToastService.ShowToast2(userResult.Reason, Enums.ToastType.Warning); + return; + } + + var user = userResult.Value; await UserManager.ConfirmEmailAsync(user, await UserManager.GenerateEmailConfirmationTokenAsync(user)); diff --git a/Server/Pages/Shared/_Layout.cshtml b/Server/Pages/Shared/_Layout.cshtml index fc62ddbd..535b01ae 100644 --- a/Server/Pages/Shared/_Layout.cshtml +++ b/Server/Pages/Shared/_Layout.cshtml @@ -1,5 +1,6 @@ @using Microsoft.AspNetCore.Hosting @using Microsoft.AspNetCore.Mvc.ViewEngines +@using Microsoft.EntityFrameworkCore; @using Remotely.Server.Services @using Remotely.Shared.Models @inject IApplicationConfig AppConfig @@ -9,14 +10,18 @@ @{ var organizationName = "Remotely"; - var user = DataService.GetUserByNameWithOrg(User?.Identity?.Name); + var userResult = await DataService.GetUserByName( + $"{User?.Identity?.Name}", + query => query.Include(x => x.Organization)); + + var user = userResult.Value; if (user is null) { - var defaultOrg = await DataService.GetDefaultOrganization(); - if (!string.IsNullOrWhiteSpace(defaultOrg?.OrganizationName)) + var orgResult = await DataService.GetDefaultOrganization(); + if (orgResult.IsSuccess) { - organizationName = defaultOrg.OrganizationName; + organizationName = orgResult.Value.OrganizationName; } } else if (!string.IsNullOrWhiteSpace(user.Organization?.OrganizationName)) @@ -43,7 +48,7 @@ @if (user is RemotelyUser) { - switch (user.UserOptions.Theme) + switch (user.UserOptions?.Theme ?? default) { case Remotely.Shared.Enums.Theme.Light: diff --git a/Server/Pages/_Host.cshtml b/Server/Pages/_Host.cshtml index df5db931..26289ed6 100644 --- a/Server/Pages/_Host.cshtml +++ b/Server/Pages/_Host.cshtml @@ -8,7 +8,8 @@ @{ Layout = null; - var user = DataService.GetUserByNameWithOrg(User?.Identity?.Name); + var userResult = await DataService.GetUserByName($"{User?.Identity?.Name}"); + var user = userResult.Value; } @@ -26,7 +27,7 @@ @if (user is RemotelyUser) { - switch (user.UserOptions.Theme) + switch (user.UserOptions?.Theme ?? default) { case Remotely.Shared.Enums.Theme.Light: diff --git a/Server/Services/CircuitManager.cs b/Server/Services/CircuitManager.cs index 48b9352d..ad44fa7b 100644 --- a/Server/Services/CircuitManager.cs +++ b/Server/Services/CircuitManager.cs @@ -4,6 +4,7 @@ using Remotely.Server.Models; using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading.Tasks; @@ -13,9 +14,9 @@ public interface ICircuitManager { ICollection Connections { get; } bool TryAddConnection(string id, ICircuitConnection connection); - bool TryRemoveConnection(string id, out ICircuitConnection connection); - Task InvokeOnConnection(string browserConnectionId, CircuitEventName eventName, params object[] args); - bool TryGetConnection(string browserConnectionId, out ICircuitConnection connection); + bool TryRemoveConnection(string id, [NotNullWhen(true)] out ICircuitConnection? connection); + Task InvokeOnConnection(string id, CircuitEventName eventName, params object[] args); + bool TryGetConnection(string id, [NotNullWhen(true)] out ICircuitConnection? connection); } public class CircuitManager : ICircuitManager { @@ -52,12 +53,12 @@ public class CircuitManager : ICircuitManager return _connections.TryAdd(id, connection); } - public bool TryGetConnection(string connectionId, out ICircuitConnection connection) + public bool TryGetConnection(string id, [NotNullWhen(true)] out ICircuitConnection? connection) { - return _connections.TryGetValue(connectionId, out connection); + return _connections.TryGetValue(id, out connection); } - public bool TryRemoveConnection(string id, out ICircuitConnection connection) + public bool TryRemoveConnection(string id, [NotNullWhen(true)] out ICircuitConnection? connection) { return _connections.TryRemove(id, out connection); } diff --git a/Server/Services/ClientAppState.cs b/Server/Services/ClientAppState.cs index 859bd6df..95d283d3 100644 --- a/Server/Services/ClientAppState.cs +++ b/Server/Services/ClientAppState.cs @@ -89,9 +89,13 @@ public class ClientAppState : ViewModelBase, IClientAppState { if (await _authService.IsAuthenticated()) { - var user = await _authService.GetUser(); - return user?.UserOptions?.Theme ?? _appConfig.Theme; + var userResult = await _authService.GetUser(); + if (userResult.IsSuccess) + { + return userResult.Value.UserOptions?.Theme ?? _appConfig.Theme; + } } + return _appConfig.Theme; } diff --git a/Server/Services/DataService.cs b/Server/Services/DataService.cs index cfafa998..bf6dc384 100644 --- a/Server/Services/DataService.cs +++ b/Server/Services/DataService.cs @@ -214,7 +214,7 @@ public interface IDataService Task> UpdateDevice(DeviceSetupOptions deviceOptions, string organizationId); - Task UpdateDevice(string deviceId, string tag, string alias, string deviceGroupId, string notes); + Task UpdateDevice(string deviceId, string? tag, string? alias, string? deviceGroupId, string? notes); Task UpdateOrganizationName(string orgId, string newName); @@ -1448,6 +1448,11 @@ public class DataService : IDataService public async Task> GetOrganizationByUserName(string userName) { + if (string.IsNullOrWhiteSpace(userName)) + { + return Result.Fail("User name is required."); + } + using var dbContext = _appDbFactory.GetContext(); var user = await dbContext @@ -1493,6 +1498,11 @@ public class DataService : IDataService public async Task> GetOrganizationNameByUserName(string userName) { + if (string.IsNullOrWhiteSpace(userName)) + { + return Result.Fail("Username cannot be empty."); + } + using var dbContext = _appDbFactory.GetContext(); var user = await dbContext.Users @@ -1737,6 +1747,15 @@ public class DataService : IDataService public async Task JoinViaInvitation(string userName, string inviteId) { + if (string.IsNullOrWhiteSpace(userName)) + { + return Result.Fail("Username cannot be empty."); + } + if (string.IsNullOrWhiteSpace(inviteId)) + { + return Result.Fail("Invite ID cannot be empty."); + } + using var dbContext = _appDbFactory.GetContext(); var invite = await dbContext.InviteLinks.FirstOrDefaultAsync(x => @@ -2014,7 +2033,7 @@ public class DataService : IDataService await dbContext.SaveChangesAsync(); } - public async Task UpdateDevice(string deviceId, string tag, string alias, string deviceGroupId, string notes) + public async Task UpdateDevice(string deviceId, string? tag, string? alias, string? deviceGroupId, string? notes) { using var dbContext = _appDbFactory.GetContext(); diff --git a/Server/Services/RcImplementations/ViewerPageDataProvider.cs b/Server/Services/RcImplementations/ViewerPageDataProvider.cs index d7472a0f..31df8799 100644 --- a/Server/Services/RcImplementations/ViewerPageDataProvider.cs +++ b/Server/Services/RcImplementations/ViewerPageDataProvider.cs @@ -68,21 +68,22 @@ public class ViewerPageDataProvider : IViewerPageDataProvider //return Task.FromResult(appTheme); } - public Task GetUserDisplayName(PageModel pageModel) + public async Task GetUserDisplayName(PageModel pageModel) { if (string.IsNullOrWhiteSpace(pageModel?.User?.Identity?.Name)) { - return Task.FromResult(string.Empty); + return string.Empty; } - var user = _dataService.GetUserByNameWithOrg(pageModel.User.Identity.Name); + var userResult = await _dataService.GetUserByName(pageModel.User.Identity.Name); - if (user is null) + if (!userResult.IsSuccess) { - return Task.FromResult(string.Empty); + return string.Empty; } + var user = userResult.Value; var displayName = user.UserOptions?.DisplayName ?? user.UserName ?? string.Empty; - return Task.FromResult(displayName); + return displayName; } } diff --git a/Shared/Models/Device.cs b/Shared/Models/Device.cs index 87aced45..865aed44 100644 --- a/Shared/Models/Device.cs +++ b/Shared/Models/Device.cs @@ -91,7 +91,7 @@ public class Device [StringLength(200)] [Sortable] [Display(Name = "Tags")] - public string Tags { get; set; } = ""; + public string? Tags { get; set; } [Sortable] [Display(Name = "Memory Total")] diff --git a/Tests/Server.Tests/DataServiceTests.cs b/Tests/Server.Tests/DataServiceTests.cs index 2b55839f..afec5c7c 100644 --- a/Tests/Server.Tests/DataServiceTests.cs +++ b/Tests/Server.Tests/DataServiceTests.cs @@ -16,8 +16,8 @@ namespace Remotely.Tests; public class DataServiceTests { private readonly string _newDeviceID = "NewDeviceName"; - private IDataService _dataService; - private TestData _testData; + private IDataService _dataService = null!; + private TestData _testData = null!; [TestMethod] public async Task AddAlert() @@ -32,7 +32,7 @@ public class DataServiceTests [TestMethod] public async Task AddOrUpdateDevice() { - var storedDevice = _dataService.GetDevice(_newDeviceID); + var storedDevice = (await _dataService.GetDevice(_newDeviceID)).Value; Assert.IsNull(storedDevice); @@ -47,9 +47,9 @@ public class DataServiceTests var result = await _dataService.AddOrUpdateDevice(newDevice); Assert.IsTrue(result.IsSuccess); - storedDevice = _dataService.GetDevice(_newDeviceID); + storedDevice = (await _dataService.GetDevice(_newDeviceID)).Value; - Assert.AreEqual(_newDeviceID, storedDevice.ID); + Assert.AreEqual(_newDeviceID, storedDevice!.ID); Assert.AreEqual(Environment.MachineName, storedDevice.DeviceName); Assert.AreEqual(Environment.Is64BitOperatingSystem, storedDevice.Is64Bit); } @@ -76,12 +76,12 @@ public class DataServiceTests [TestMethod] public void DeviceGroupPermissions() { - Assert.AreEqual(2, _dataService.GetDevicesForUser(_testData.Org1Admin1.UserName).Length); - Assert.AreEqual(2, _dataService.GetDevicesForUser(_testData.Org1Admin2.UserName).Length); - Assert.AreEqual(0, _dataService.GetDevicesForUser(_testData.Org1User1.UserName).Length); - Assert.AreEqual(0, _dataService.GetDevicesForUser(_testData.Org1User2.UserName).Length); - Assert.AreEqual(0, _dataService.GetDevicesForUser(_testData.Org2User1.UserName).Length); - Assert.AreEqual(0, _dataService.GetDevicesForUser(_testData.Org2User2.UserName).Length); + Assert.AreEqual(2, _dataService.GetDevicesForUser(_testData.Org1Admin1.UserName!).Length); + Assert.AreEqual(2, _dataService.GetDevicesForUser(_testData.Org1Admin2.UserName!).Length); + Assert.AreEqual(0, _dataService.GetDevicesForUser(_testData.Org1User1.UserName!).Length); + Assert.AreEqual(0, _dataService.GetDevicesForUser(_testData.Org1User2.UserName!).Length); + Assert.AreEqual(0, _dataService.GetDevicesForUser(_testData.Org2User1.UserName!).Length); + Assert.AreEqual(0, _dataService.GetDevicesForUser(_testData.Org2User2.UserName!).Length); Assert.IsTrue(_dataService.DoesUserHaveAccessToDevice(_testData.Org1Device1.ID, _testData.Org1Admin1)); Assert.IsTrue(_dataService.DoesUserHaveAccessToDevice(_testData.Org1Device1.ID, _testData.Org1Admin2)); @@ -91,16 +91,16 @@ public class DataServiceTests Assert.IsFalse(_dataService.DoesUserHaveAccessToDevice(_testData.Org1Device1.ID, _testData.Org2User2)); var groupID = _testData.Org1Group1.ID; - _dataService.AddUserToDeviceGroup(_testData.Org1Id, groupID, _testData.Org1User1.UserName, out _); + _dataService.AddUserToDeviceGroup(_testData.Org1Id, groupID, _testData.Org1User1.UserName!, out _); _testData.Org1Device1.DeviceGroupID = groupID; _dataService.UpdateDevice(_testData.Org1Device1.ID, "", "", groupID, ""); - Assert.AreEqual(2, _dataService.GetDevicesForUser(_testData.Org1Admin1.UserName).Length); - Assert.AreEqual(2, _dataService.GetDevicesForUser(_testData.Org1Admin2.UserName).Length); - Assert.AreEqual(1, _dataService.GetDevicesForUser(_testData.Org1User1.UserName).Length); - Assert.AreEqual(0, _dataService.GetDevicesForUser(_testData.Org1User2.UserName).Length); - Assert.AreEqual(0, _dataService.GetDevicesForUser(_testData.Org2User1.UserName).Length); - Assert.AreEqual(0, _dataService.GetDevicesForUser(_testData.Org2User2.UserName).Length); + Assert.AreEqual(2, _dataService.GetDevicesForUser(_testData.Org1Admin1.UserName!).Length); + Assert.AreEqual(2, _dataService.GetDevicesForUser(_testData.Org1Admin2.UserName!).Length); + Assert.AreEqual(1, _dataService.GetDevicesForUser(_testData.Org1User1.UserName!).Length); + Assert.AreEqual(0, _dataService.GetDevicesForUser(_testData.Org1User2.UserName!).Length); + Assert.AreEqual(0, _dataService.GetDevicesForUser(_testData.Org2User1.UserName!).Length); + Assert.AreEqual(0, _dataService.GetDevicesForUser(_testData.Org2User2.UserName!).Length); Assert.IsTrue(_dataService.DoesUserHaveAccessToDevice(_testData.Org1Device1.ID, _testData.Org1Admin1)); Assert.IsTrue(_dataService.DoesUserHaveAccessToDevice(_testData.Org1Device1.ID, _testData.Org1Admin2)); @@ -110,12 +110,12 @@ public class DataServiceTests Assert.IsFalse(_dataService.DoesUserHaveAccessToDevice(_testData.Org1Device1.ID, _testData.Org2User2)); var allDevices = _dataService.GetAllDevices(_testData.Org1Id).Select(x => x.ID).ToArray(); - Assert.AreEqual(2, _dataService.FilterDeviceIDsByUserPermission(allDevices, _testData.Org1Admin1).Length); - Assert.AreEqual(2, _dataService.FilterDeviceIDsByUserPermission(allDevices, _testData.Org1Admin2).Length); - Assert.AreEqual(1, _dataService.FilterDeviceIDsByUserPermission(allDevices, _testData.Org1User1).Length); - Assert.AreEqual(0, _dataService.FilterDeviceIDsByUserPermission(allDevices, _testData.Org1User2).Length); - Assert.AreEqual(0, _dataService.FilterDeviceIDsByUserPermission(allDevices, _testData.Org2User1).Length); - Assert.AreEqual(0, _dataService.FilterDeviceIDsByUserPermission(allDevices, _testData.Org2User2).Length); + Assert.AreEqual(2, _dataService.FilterDeviceIdsByUserPermission(allDevices, _testData.Org1Admin1).Length); + Assert.AreEqual(2, _dataService.FilterDeviceIdsByUserPermission(allDevices, _testData.Org1Admin2).Length); + Assert.AreEqual(1, _dataService.FilterDeviceIdsByUserPermission(allDevices, _testData.Org1User1).Length); + Assert.AreEqual(0, _dataService.FilterDeviceIdsByUserPermission(allDevices, _testData.Org1User2).Length); + Assert.AreEqual(0, _dataService.FilterDeviceIdsByUserPermission(allDevices, _testData.Org2User1).Length); + Assert.AreEqual(0, _dataService.FilterDeviceIdsByUserPermission(allDevices, _testData.Org2User2).Length); } [TestMethod] @@ -198,12 +198,12 @@ public class DataServiceTests } [TestMethod] - public void UpdateOrganizationName() + public async Task UpdateOrganizationName() { - Assert.AreEqual("Org1", _testData.Org1Admin1.Organization.OrganizationName); - _dataService.UpdateOrganizationName(_testData.Org1Id, "Test Org"); - var updatedOrg = _dataService.GetOrganizationById(_testData.Org1Id); - Assert.AreEqual("Test Org", updatedOrg.OrganizationName); + Assert.AreEqual("Org1", _testData.Org1Admin1.Organization!.OrganizationName); + await _dataService.UpdateOrganizationName(_testData.Org1Id, "Test Org"); + var updatedOrg = (await _dataService.GetOrganizationById(_testData.Org1Id)).Value; + Assert.AreEqual("Test Org", updatedOrg!.OrganizationName); } [TestMethod] @@ -217,8 +217,8 @@ public class DataServiceTests currentAdmins = _dataService.GetServerAdmins(); Assert.AreEqual(2, currentAdmins.Count); - Assert.IsTrue(currentAdmins.Contains(_testData.Org1Admin1.UserName)); - Assert.IsTrue(currentAdmins.Contains(_testData.Org1Admin2.UserName)); + Assert.IsTrue(currentAdmins.Contains(_testData.Org1Admin1.UserName!)); + Assert.IsTrue(currentAdmins.Contains(_testData.Org1Admin2.UserName!)); // Shouldn't be able to change themselves. await _dataService.SetIsServerAdmin(_testData.Org1Admin2.Id, false, _testData.Org1Admin2.Id); @@ -237,12 +237,12 @@ public class DataServiceTests } [TestMethod] - public void VerifyInitialData() + public async Task VerifyInitialData() { - Assert.IsNotNull(_dataService.GetUserByNameWithOrg(_testData.Org1Admin1.UserName)); - Assert.IsNotNull(_dataService.GetUserByNameWithOrg(_testData.Org1Admin2.UserName)); - Assert.IsNotNull(_dataService.GetUserByNameWithOrg(_testData.Org1User1.UserName)); - Assert.IsNotNull(_dataService.GetUserByNameWithOrg(_testData.Org1User2.UserName)); + Assert.IsNotNull((await _dataService.GetUserByName(_testData.Org1Admin1.UserName!)).Value); + Assert.IsNotNull((await _dataService.GetUserByName(_testData.Org1Admin2.UserName!)).Value); + Assert.IsNotNull((await _dataService.GetUserByName(_testData.Org1User1.UserName!)).Value); + Assert.IsNotNull((await _dataService.GetUserByName(_testData.Org1User2.UserName!)).Value); Assert.AreEqual(2, _dataService.GetOrganizationCount()); var devices1 = _dataService.GetAllDevices(_testData.Org1Id); diff --git a/Tests/Server.Tests/TestData.cs b/Tests/Server.Tests/TestData.cs index 0800ef50..14089fa6 100644 --- a/Tests/Server.Tests/TestData.cs +++ b/Tests/Server.Tests/TestData.cs @@ -17,7 +17,7 @@ namespace Remotely.Tests; public class TestData { #region Organization1 - public Organization Org1 => Org1Admin1.Organization; + public Organization Org1 => Org1Admin1.Organization!; public RemotelyUser Org1Admin1 { get; } = new() { @@ -28,11 +28,11 @@ public class TestData UserOptions = new RemotelyUserOptions() }; - public RemotelyUser Org1Admin2 { get; private set; } + public RemotelyUser Org1Admin2 { get; private set; } = null!; - public Device Org1Device1 { get; private set; } + public Device Org1Device1 { get; private set; } = null!; - public Device Org1Device2 { get; private set; } + public Device Org1Device2 { get; private set; } = null!; public DeviceGroup Org1Group1 { get; private set; } = new DeviceGroup() { @@ -45,14 +45,14 @@ public class TestData }; public string Org1Id => Org1.ID; - public RemotelyUser Org1User1 { get; private set; } - public RemotelyUser Org1User2 { get; private set; } + public RemotelyUser Org1User1 { get; private set; } = null!; + public RemotelyUser Org1User2 { get; private set; } = null!; #endregion #region Organization2 - public Organization Org2 => Org2Admin1.Organization; + public Organization Org2 => Org2Admin1.Organization!; public RemotelyUser Org2Admin1 { get; } = new() { @@ -63,11 +63,11 @@ public class TestData UserOptions = new RemotelyUserOptions() }; - public RemotelyUser Org2Admin2 { get; private set; } + public RemotelyUser Org2Admin2 { get; private set; } = null!; - public Device Org2Device1 { get; private set; } + public Device Org2Device1 { get; private set; } = null!; - public Device Org2Device2 { get; private set; } + public Device Org2Device2 { get; private set; } = null!; public DeviceGroup Org2Group1 { get; private set; } = new DeviceGroup() { @@ -80,8 +80,8 @@ public class TestData }; public string Org2Id => Org2.ID; - public RemotelyUser Org2User1 { get; private set; } - public RemotelyUser Org2User2 { get; private set; } + public RemotelyUser Org2User1 { get; private set; } = null!; + public RemotelyUser Org2User2 { get; private set; } = null!; #endregion public void ClearData() @@ -106,13 +106,13 @@ public class TestData await userManager.CreateAsync(Org1Admin1); await dataService.CreateUser("org1admin2@test.com", true, Org1Admin1.OrganizationID); - Org1Admin2 = dataService.GetUserByNameWithOrg("org1admin2@test.com"); + Org1Admin2 = (await dataService.GetUserByName("org1admin2@test.com")).Value!; await dataService.CreateUser("org1testuser1@test.com", false, Org1Admin1.OrganizationID); - Org1User1 = dataService.GetUserByNameWithOrg("org1testuser1@test.com"); + Org1User1 = (await dataService.GetUserByName("org1testuser1@test.com")).Value!; await dataService.CreateUser("org1testuser2@test.com", false, Org1Admin1.OrganizationID); - Org1User2 = dataService.GetUserByNameWithOrg("org1testuser2@test.com"); + Org1User2 = (await dataService.GetUserByName("org1testuser2@test.com")).Value!; var device1 = new DeviceClientDto() { @@ -126,12 +126,12 @@ public class TestData DeviceName = "Org1Device2Name", OrganizationID = Org1Id }; - Org1Device1 = (await dataService.AddOrUpdateDevice(device1)).Value; - Org1Device2 = (await dataService.AddOrUpdateDevice(device2)).Value; + Org1Device1 = (await dataService.AddOrUpdateDevice(device1)).Value!; + Org1Device2 = (await dataService.AddOrUpdateDevice(device2)).Value!; await dataService.AddDeviceGroup(Org1Admin1.OrganizationID, Org1Group1); await dataService.AddDeviceGroup(Org1Admin1.OrganizationID, Org1Group2); - var deviceGroups1 = dataService.GetDeviceGroups(Org1Admin1.UserName); + var deviceGroups1 = dataService.GetDeviceGroups(Org1Admin1.UserName!); Org1Group1 = deviceGroups1.First(x => x.Name == Org1Group1.Name); Org1Group2 = deviceGroups1.First(x => x.Name == Org1Group2.Name); @@ -140,13 +140,13 @@ public class TestData await userManager.CreateAsync(Org2Admin1); await dataService.CreateUser("org2admin2@test.com", true, Org2Admin1.OrganizationID); - Org2Admin2 = dataService.GetUserByNameWithOrg("org2admin2@test.com"); + Org2Admin2 = (await dataService.GetUserByName("org2admin2@test.com")).Value!; await dataService.CreateUser("org2testuser1@test.com", false, Org2Admin1.OrganizationID); - Org2User1 = dataService.GetUserByNameWithOrg("org2testuser1@test.com"); + Org2User1 = (await dataService.GetUserByName("org2testuser1@test.com")).Value!; await dataService.CreateUser("org2testuser2@test.com", false, Org2Admin1.OrganizationID); - Org2User2 = dataService.GetUserByNameWithOrg("org2testuser2@test.com"); + Org2User2 = (await dataService.GetUserByName("org2testuser2@test.com")).Value!; var device3 = new DeviceClientDto() { @@ -160,12 +160,12 @@ public class TestData DeviceName = "Org2Device2Name", OrganizationID = Org2Id }; - Org2Device1 = (await dataService.AddOrUpdateDevice(device3)).Value; - Org2Device2 = (await dataService.AddOrUpdateDevice(device4)).Value; + Org2Device1 = (await dataService.AddOrUpdateDevice(device3)).Value!; + Org2Device2 = (await dataService.AddOrUpdateDevice(device4)).Value!; await dataService.AddDeviceGroup(Org2Admin1.OrganizationID, Org2Group1); await dataService.AddDeviceGroup(Org2Admin1.OrganizationID, Org2Group2); - var deviceGroups2 = dataService.GetDeviceGroups(Org2Admin1.UserName); + var deviceGroups2 = dataService.GetDeviceGroups(Org2Admin1.UserName!); Org2Group1 = deviceGroups2.First(x => x.Name == Org2Group1.Name); Org2Group2 = deviceGroups2.First(x => x.Name == Org2Group2.Name); }