diff --git a/src/Pages/SetupInternalWallet.razor b/src/Pages/SetupInternalWallet.razor index bf2cb73b..9cc3feeb 100644 --- a/src/Pages/SetupInternalWallet.razor +++ b/src/Pages/SetupInternalWallet.razor @@ -1,5 +1,7 @@ @page "/setup-internal-wallet" @using System.Text.RegularExpressions +@using NodeGuard.Data.Models +@using NodeGuard.Services

Internal wallet setup

@attribute [Authorize(Roles = "Superadmin")] @@ -85,6 +87,9 @@ [Inject] public IToastService ToastService { get; set; } + [Inject] + public IAuditService AuditService { get; set; } + private InternalWallet? _internalWallet; private bool _isRemoteSignerModeEnabled = false; @@ -154,6 +159,12 @@ if (updateResult.Item1) { ToastService.ShowSuccess("Internal wallet setup completed"); + await AuditService.LogAsync( + AuditActionType.GenerateInternalWallet, + AuditEventType.Success, + AuditObjectType.InternalWallet, + _internalWallet.Id.ToString(), + new { IsRemoteSigner = _isRemoteSignerModeEnabled }); NavigationManager.NavigateTo("/"); } else diff --git a/src/Pages/Users.razor b/src/Pages/Users.razor index d5272c5f..41dbbd7a 100644 --- a/src/Pages/Users.razor +++ b/src/Pages/Users.razor @@ -117,6 +117,7 @@ @inject IToastService ToastService @inject INodeRepository NodeRepository @inject ILocalStorageService LocalStorageService +@inject IAuditService AuditService @attribute [Authorize(Roles = "Superadmin")] @code { private List _users = new(); @@ -211,13 +212,24 @@ if (updateResult.Item1 && updateUserRoles.Item1) { ToastService.ShowSuccess("Success"); + await AuditService.LogAsync( + AuditActionType.Create, + AuditEventType.Success, + AuditObjectType.User, + arg.Item.Id, + new { Username = arg.Item.UserName, Roles = string.Join(", ", _selectedRoles) }); await GetData(); } else { ToastService.ShowError("Something went wrong"); _users.Remove(arg.Item); - + await AuditService.LogAsync( + AuditActionType.Create, + AuditEventType.Failure, + AuditObjectType.User, + null, + new { Username = arg.Item.UserName }); } } @@ -276,10 +288,22 @@ if (updateResult2.Item1 && clearResult.Item1 && updateUserRoles.Item1) { ToastService.ShowSuccess("Success"); + await AuditService.LogAsync( + AuditActionType.Update, + AuditEventType.Success, + AuditObjectType.User, + arg.Item.Id, + new { Username = arg.Item.UserName, Roles = string.Join(", ", _selectedRoles) }); } else { ToastService.ShowError("Something went wrong"); + await AuditService.LogAsync( + AuditActionType.Update, + AuditEventType.Failure, + AuditObjectType.User, + arg.Item.Id, + new { Username = arg.Item.UserName }); } await GetData(); @@ -348,11 +372,22 @@ if (lockResult.Item1) { ToastService.ShowSuccess("User unlocked"); + await AuditService.LogAsync( + AuditActionType.UnlockUser, + AuditEventType.Success, + AuditObjectType.User, + contextItem.Id, + new { Username = contextItem.UserName }); } else { ToastService.ShowError("Something went wrong"); - + await AuditService.LogAsync( + AuditActionType.UnlockUser, + AuditEventType.Failure, + AuditObjectType.User, + contextItem.Id, + new { Username = contextItem.UserName }); } await GetData(); @@ -369,11 +404,22 @@ if (lockResult.Item1) { ToastService.ShowSuccess("User locked out"); + await AuditService.LogAsync( + AuditActionType.LockUser, + AuditEventType.Success, + AuditObjectType.User, + contextItem.Id, + new { Username = contextItem.UserName }); } else { ToastService.ShowError("Something went wrong"); - + await AuditService.LogAsync( + AuditActionType.LockUser, + AuditEventType.Failure, + AuditObjectType.User, + contextItem.Id, + new { Username = contextItem.UserName }); } await GetData(); diff --git a/src/Pages/Wallets.razor b/src/Pages/Wallets.razor index 608aecff..5326dbd9 100644 --- a/src/Pages/Wallets.razor +++ b/src/Pages/Wallets.razor @@ -24,6 +24,7 @@ @inject IPriceConversionService PriceConversionService @inject INBXplorerService NBXplorerService @inject IUTXOTagRepository UTXOTagRepository +@inject IAuditService AuditService @attribute [Authorize(Roles = "NodeManager, FinanceManager, Superadmin")] @@ -910,11 +911,29 @@ OnSubmit="TransferFundsHotWallet"/> if (addResult.Item1) { ToastService.ShowSuccess("Success"); + await AuditService.LogAsync( + AuditActionType.Create, + AuditEventType.Success, + AuditObjectType.Wallet, + arg.Item.Id.ToString(), + LoggedUser?.Id, + LoggedUser?.UserName, + null, + new { Name = arg.Item.Name, IsHotWallet = arg.Item.IsHotWallet, MofN = arg.Item.MofN }); await GetData(); } else { ToastService.ShowError("Something went wrong"); + await AuditService.LogAsync( + AuditActionType.Create, + AuditEventType.Failure, + AuditObjectType.Wallet, + null, + LoggedUser?.Id, + LoggedUser?.UserName, + null, + new { Name = arg.Item.Name, Error = addResult.Item2 }); _wallets.Remove(arg.Item); } } @@ -934,10 +953,28 @@ OnSubmit="TransferFundsHotWallet"/> { arg.Cancel = true; ToastService.ShowError("Something went wrong"); + await AuditService.LogAsync( + AuditActionType.Delete, + AuditEventType.Failure, + AuditObjectType.Wallet, + arg.Item.Id.ToString(), + LoggedUser?.Id, + LoggedUser?.UserName, + null, + new { Name = arg.Item.Name, Error = message }); } else { ToastService.ShowSuccess("Success"); + await AuditService.LogAsync( + AuditActionType.Delete, + AuditEventType.Success, + AuditObjectType.Wallet, + arg.Item.Id.ToString(), + LoggedUser?.Id, + LoggedUser?.UserName, + null, + new { Name = arg.Item.Name }); await GetData(); } } @@ -969,10 +1006,28 @@ OnSubmit="TransferFundsHotWallet"/> if (updateResult.Item1) { ToastService.ShowSuccess("Success"); + await AuditService.LogAsync( + AuditActionType.Update, + AuditEventType.Success, + AuditObjectType.Wallet, + arg.Item.Id.ToString(), + LoggedUser?.Id, + LoggedUser?.UserName, + null, + new { Name = arg.Item.Name, IsHotWallet = arg.Item.IsHotWallet }); } else { ToastService.ShowError("Something went wrong"); + await AuditService.LogAsync( + AuditActionType.Update, + AuditEventType.Failure, + AuditObjectType.Wallet, + arg.Item.Id.ToString(), + LoggedUser?.Id, + LoggedUser?.UserName, + null, + new { Name = arg.Item.Name, Error = updateResult.Item2 }); } await GetData(); @@ -1032,10 +1087,28 @@ OnSubmit="TransferFundsHotWallet"/> if (updateResult.Item1) { ToastService.ShowSuccess("Key added"); + await AuditService.LogAsync( + AuditActionType.AddKey, + AuditEventType.Success, + AuditObjectType.Wallet, + _selectedWallet.Id.ToString(), + LoggedUser?.Id, + LoggedUser?.UserName, + null, + new { WalletName = _selectedWallet.Name, KeyId = _selectedWalletKey.Id }); } else { ToastService.ShowError("Error while adding key..."); + await AuditService.LogAsync( + AuditActionType.AddKey, + AuditEventType.Failure, + AuditObjectType.Wallet, + _selectedWallet.Id.ToString(), + LoggedUser?.Id, + LoggedUser?.UserName, + null, + new { WalletName = _selectedWallet.Name, KeyId = _selectedWalletKey.Id, Error = updateResult.Item2 }); } } @@ -1241,16 +1314,36 @@ OnSubmit="TransferFundsHotWallet"/> if (_selectedWalletToFinalise == null || _selectedWalletToFinalise.IsFinalised) return; + var walletId = _selectedWalletToFinalise.Id; + var walletName = _selectedWalletToFinalise.Name; var result = await WalletRepository.FinaliseWallet(_selectedWalletToFinalise); if (result.Item1) { ToastService.ShowSuccess("Success"); + await AuditService.LogAsync( + AuditActionType.Finalise, + AuditEventType.Success, + AuditObjectType.Wallet, + walletId.ToString(), + LoggedUser?.Id, + LoggedUser?.UserName, + null, + new { Name = walletName }); } else { ToastService.ShowError("Error while marking wallet as finalised"); + await AuditService.LogAsync( + AuditActionType.Finalise, + AuditEventType.Failure, + AuditObjectType.Wallet, + walletId.ToString(), + LoggedUser?.Id, + LoggedUser?.UserName, + null, + new { Name = walletName, Error = result.Item2 }); } _selectedWalletToFinalise = null; @@ -1330,6 +1423,15 @@ OnSubmit="TransferFundsHotWallet"/> if (!result.Item1) { ToastService.ShowError("Something went wrong while importing the wallet"); + await AuditService.LogAsync( + AuditActionType.Import, + AuditEventType.Failure, + AuditObjectType.Wallet, + null, + LoggedUser?.Id, + LoggedUser?.UserName, + null, + new { Name = _name, IsWatchOnly = _IsImportWalletModalWatchOnly, Error = result.Item2 }); return; } @@ -1338,6 +1440,15 @@ OnSubmit="TransferFundsHotWallet"/> //Success ToastService.ShowSuccess("Wallet imported successfully"); + await AuditService.LogAsync( + AuditActionType.Import, + AuditEventType.Success, + AuditObjectType.Wallet, + null, + LoggedUser?.Id, + LoggedUser?.UserName, + null, + new { Name = _name, IsWatchOnly = _IsImportWalletModalWatchOnly }); //Close modal await CloseAndCleanImportWalletModal(); @@ -1493,9 +1604,38 @@ OnSubmit="TransferFundsHotWallet"/> if (transferSuccess) { ToastService.ShowSuccess("Funds transferred successfully"); + await AuditService.LogAsync( + AuditActionType.Transfer, + AuditEventType.Success, + AuditObjectType.Wallet, + _sourceTransferWallet?.Id.ToString(), + LoggedUser?.Id, + LoggedUser?.UserName, + null, + new { + SourceWallet = _sourceWalletName, + TargetWallet = _targetWalletName, + Amount = _amountToTransfer, + AllFunds = _transferAllFunds, + WithdrawalRequestId = withdrawalRequest.Id + }); } else { + await AuditService.LogAsync( + AuditActionType.Transfer, + AuditEventType.Failure, + AuditObjectType.Wallet, + _sourceTransferWallet?.Id.ToString(), + LoggedUser?.Id, + LoggedUser?.UserName, + null, + new { + SourceWallet = _sourceWalletName, + TargetWallet = _targetWalletName, + Amount = _amountToTransfer, + WithdrawalRequestId = withdrawalRequest.Id + }); ToastService.ShowError("Error while transferring funds, please contact a superadmin for troubleshooting"); } @@ -1741,9 +1881,28 @@ OnSubmit="TransferFundsHotWallet"/> if (!saved) { ToastService.ShowError("Error while updating the UTXO status"); + await AuditService.LogAsync( + newValue ? AuditActionType.FreezeUTXO : AuditActionType.UnfreezeUTXO, + AuditEventType.Failure, + AuditObjectType.UTXO, + utxo.Outpoint.ToString(), + LoggedUser?.Id, + LoggedUser?.UserName, + null, + new { WalletId = _selectedWallet?.Id, Outpoint = utxo.Outpoint.ToString() }); return; } + await AuditService.LogAsync( + newValue ? AuditActionType.FreezeUTXO : AuditActionType.UnfreezeUTXO, + AuditEventType.Success, + AuditObjectType.UTXO, + utxo.Outpoint.ToString(), + LoggedUser?.Id, + LoggedUser?.UserName, + null, + new { WalletId = _selectedWallet?.Id, Outpoint = utxo.Outpoint.ToString() }); + // Updated the UI _detailsUTXOs = _detailsUTXOs.Select(x => { diff --git a/src/Shared/NavMenu.razor b/src/Shared/NavMenu.razor index c261bff8..ca3a0120 100644 --- a/src/Shared/NavMenu.razor +++ b/src/Shared/NavMenu.razor @@ -73,6 +73,14 @@ + + + + diff --git a/src/Shared/NewSwapModal.razor b/src/Shared/NewSwapModal.razor index 6f883815..bb98c50f 100644 --- a/src/Shared/NewSwapModal.razor +++ b/src/Shared/NewSwapModal.razor @@ -207,6 +207,7 @@ @inject IBitcoinService BitcoinService @inject IPriceConversionService PriceConversionService @inject ILogger Logger +@inject IAuditService AuditService @inherits CancellableComponent @code { [CascadingParameter] public required ApplicationUser LoggedUser { get; set; } @@ -307,6 +308,28 @@ UserRequestorId = LoggedUser.Id, }); + // Audit successful manual swap out creation + await AuditService.LogAsync( + AuditActionType.SwapOutInitiated, + AuditEventType.Success, + AuditObjectType.SwapOut, + response.Id, + LoggedUser?.Id, + LoggedUser?.UserName, + null, + new + { + NodeId = _selectedNode.Id, + NodeName = _selectedNode.Name, + Provider = _selectedProvider.ToString(), + AmountBtc = _amountBtc, + AmountSats = response.Amount, + DestinationWalletId = _selectedWallet.Id, + DestinationWalletName = _selectedWallet.Name, + ProviderId = response.Id, + IsManual = true + }); + ToastService.ShowSuccess("Swap created successfully"); await _confirmationModal.CloseModal();