diff --git a/src/Areas/Identity/Pages/Account/LogOut.cshtml b/src/Areas/Identity/Pages/Account/LogOut.cshtml
index ed279e7c..71f50307 100644
--- a/src/Areas/Identity/Pages/Account/LogOut.cshtml
+++ b/src/Areas/Identity/Pages/Account/LogOut.cshtml
@@ -21,9 +21,6 @@
AuditEventType.Success,
AuditObjectType.User,
userId,
- userId,
- username,
- HttpContextAccessor.HttpContext.GetClientIpAddress(),
new { Username = username });
}
@@ -42,9 +39,6 @@
AuditEventType.Success,
AuditObjectType.User,
userId,
- userId,
- username,
- HttpContextAccessor.HttpContext.GetClientIpAddress(),
new { Username = username });
}
diff --git a/src/Areas/Identity/Pages/Account/Login.cshtml.cs b/src/Areas/Identity/Pages/Account/Login.cshtml.cs
index 0b2a1236..7aa24292 100644
--- a/src/Areas/Identity/Pages/Account/Login.cshtml.cs
+++ b/src/Areas/Identity/Pages/Account/Login.cshtml.cs
@@ -140,9 +140,6 @@ await _auditService.LogAsync(
AuditEventType.Success,
AuditObjectType.User,
user?.Id,
- user?.Id,
- Input.Username,
- HttpContext.GetClientIpAddress(),
new { Username = Input.Username });
return LocalRedirect(returnUrl);
}
@@ -158,9 +155,6 @@ await _auditService.LogAsync(
AuditEventType.Failure,
AuditObjectType.User,
null,
- null,
- Input.Username,
- HttpContext.GetClientIpAddress(),
new { Username = Input.Username, Reason = "Account locked out" });
return RedirectToPage("./Lockout");
}
@@ -171,9 +165,6 @@ await _auditService.LogAsync(
AuditEventType.Failure,
AuditObjectType.User,
null,
- null,
- Input.Username,
- HttpContext.GetClientIpAddress(),
new { Username = Input.Username, Reason = "Invalid credentials" });
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
return Page();
diff --git a/src/Areas/Identity/Pages/Account/LoginWith2fa.cshtml.cs b/src/Areas/Identity/Pages/Account/LoginWith2fa.cshtml.cs
index a8838f55..a2342ab9 100644
--- a/src/Areas/Identity/Pages/Account/LoginWith2fa.cshtml.cs
+++ b/src/Areas/Identity/Pages/Account/LoginWith2fa.cshtml.cs
@@ -8,7 +8,6 @@
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Identity;
using NodeGuard.Services;
-using NodeGuard.Helpers;
namespace NodeGuard.Areas.Identity.Pages.Account
{
@@ -118,10 +117,7 @@ await _auditService.LogAsync(
AuditActionType.TwoFactorLogin,
AuditEventType.Success,
AuditObjectType.User,
- userId,
- userId,
- user.UserName,
- HttpContext.GetClientIpAddress(),
+ objectId: userId,
new { Username = user.UserName });
return LocalRedirect(returnUrl);
}
@@ -132,10 +128,7 @@ await _auditService.LogAsync(
AuditActionType.TwoFactorLogin,
AuditEventType.Failure,
AuditObjectType.User,
- userId,
- userId,
- user.UserName,
- HttpContext.GetClientIpAddress(),
+ objectId: userId,
new { Username = user.UserName, Reason = "Account locked out" });
return RedirectToPage("./Lockout");
}
@@ -146,10 +139,7 @@ await _auditService.LogAsync(
AuditActionType.TwoFactorLogin,
AuditEventType.Failure,
AuditObjectType.User,
- userId,
- userId,
- user.UserName,
- HttpContext.GetClientIpAddress(),
+ objectId: userId,
new { Username = user.UserName, Reason = "Invalid authenticator code" });
ModelState.AddModelError(string.Empty, "Invalid authenticator code.");
return Page();
diff --git a/src/Pages/ChannelRequests.razor b/src/Pages/ChannelRequests.razor
index 92e3dd82..f522affa 100644
--- a/src/Pages/ChannelRequests.razor
+++ b/src/Pages/ChannelRequests.razor
@@ -724,9 +724,6 @@
AuditEventType.Success,
AuditObjectType.ChannelOperationRequest,
request.Id.ToString(),
- LoggedUser.Id,
- LoggedUser.UserName,
- HttpContextAccessor.HttpContext?.GetClientIpAddress(),
new { Amount = amount, SourceNodeId = _selectedSourceNodeId, DestNodeId = _selectedDestNode?.Id, Description = $"Channel open request created. Amount: {amount} BTC, SourceNodeId: {_selectedSourceNodeId}, DestNodeId: {_selectedDestNode?.Id}" });
if (_selectedUTXOs.Count > 0)
@@ -742,9 +739,6 @@
AuditEventType.Failure,
AuditObjectType.ChannelOperationRequest,
null,
- LoggedUser.Id,
- LoggedUser.UserName,
- HttpContextAccessor.HttpContext?.GetClientIpAddress(),
new { Error = createChannelResult.Item2, Description = $"Failed to create channel open request. Error: {createChannelResult.Item2}" });
}
_utxoSelectorModalRef.ClearModal();
@@ -803,9 +797,6 @@
AuditEventType.Failure,
AuditObjectType.ChannelOperationRequest,
_selectedRequest.Id.ToString(),
- LoggedUser.Id,
- LoggedUser.UserName,
- HttpContextAccessor.HttpContext?.GetClientIpAddress(),
new { RequestId = _selectedRequest.Id, Status = _selectedStatus, Description = $"Failed to {_selectedStatus.ToString().ToLower()} channel operation request" });
}
else
@@ -817,9 +808,6 @@
AuditEventType.Success,
AuditObjectType.ChannelOperationRequest,
_selectedRequest.Id.ToString(),
- LoggedUser.Id,
- LoggedUser.UserName,
- HttpContextAccessor.HttpContext?.GetClientIpAddress(),
new { RequestId = _selectedRequest.Id, Status = _selectedStatus, Reason = _selectedRequest.ClosingReason, Description = $"Channel operation request {_selectedStatus.ToString().ToLower()}" });
await FetchRequests();
}
@@ -892,9 +880,6 @@
AuditEventType.Success,
AuditObjectType.ChannelOperationRequest,
_selectedRequest.Id.ToString(),
- LoggedUser.Id,
- LoggedUser.UserName,
- HttpContextAccessor.HttpContext?.GetClientIpAddress(),
new { RequestId = _selectedRequest.Id, Description = "PSBT signature collected for channel operation request" });
_selectedRequest = await ChannelOperationRequestRepository.GetById(_selectedRequest.Id);
@@ -913,9 +898,6 @@
AuditEventType.Failure,
AuditObjectType.ChannelOperationRequest,
_selectedRequest.Id.ToString(),
- LoggedUser.Id,
- LoggedUser.UserName,
- HttpContextAccessor.HttpContext?.GetClientIpAddress(),
new { RequestId = _selectedRequest.Id, Description = "Failed to save PSBT signature for channel operation request" });
}
@@ -955,9 +937,6 @@
AuditEventType.Success,
AuditObjectType.ChannelOperationRequest,
_selectedRequest.Id.ToString(),
- LoggedUser.Id,
- LoggedUser.UserName,
- HttpContextAccessor.HttpContext?.GetClientIpAddress(),
new { Amount = new Money(_selectedRequest.SatsAmount).ToUnit(MoneyUnit.BTC), SourceNodeId = _selectedRequest.SourceNodeId, DestNodeId = _selectedRequest.DestNodeId, IsHotWallet = true, Description = "Hot wallet channel open request created" });
}
else
@@ -968,9 +947,6 @@
AuditEventType.Failure,
AuditObjectType.ChannelOperationRequest,
null,
- LoggedUser.Id,
- LoggedUser.UserName,
- HttpContextAccessor.HttpContext?.GetClientIpAddress(),
new { Error = createChannelResult.Item2, IsHotWallet = true, Description = "Failed to create hot wallet channel open request" });
_utxoSelectorModalRef.ClearModal();
await _approveOperationConfirmationModal.CloseModal();
@@ -1070,9 +1046,6 @@
AuditEventType.Success,
AuditObjectType.ChannelOperationRequest,
request.Id.ToString(),
- LoggedUser.Id,
- LoggedUser.UserName,
- HttpContextAccessor.HttpContext?.GetClientIpAddress(),
new { RequestId = request.Id, NewStatus = ChannelOperationRequestStatus.Failed, Description = "Channel operation request marked as failed" });
}
catch (Exception? e)
@@ -1083,9 +1056,6 @@
AuditEventType.Failure,
AuditObjectType.ChannelOperationRequest,
_selectedRequestForMarkingAsFailed?.Id.ToString(),
- LoggedUser?.Id,
- LoggedUser?.UserName,
- HttpContextAccessor.HttpContext?.GetClientIpAddress(),
new { RequestId = _selectedRequestForMarkingAsFailed?.Id, Description = "Failed to mark channel operation request as failed" });
}
finally
diff --git a/src/Pages/Channels.razor b/src/Pages/Channels.razor
index 4764adbb..42d9cfcf 100644
--- a/src/Pages/Channels.razor
+++ b/src/Pages/Channels.razor
@@ -505,14 +505,14 @@
{
ToastService.ShowError("Something went wrong");
await AuditService.LogAsync(actionType, AuditEventType.Failure, AuditObjectType.Channel,
- channel.Id.ToString(), LoggedUser?.Id, LoggedUser?.UserName, null,
+ channel.Id.ToString(),
$"Failed to {(forceClose ? "force " : "")}close channel. ChanId: {channel.ChanId}");
}
else
{
ToastService.ShowSuccess("Channel closed successfully");
await AuditService.LogAsync(actionType, AuditEventType.Success, AuditObjectType.Channel,
- channel.Id.ToString(), LoggedUser?.Id, LoggedUser?.UserName, null,
+ channel.Id.ToString(),
$"Channel {(forceClose ? "force " : "")}closed. ChanId: {channel.ChanId}");
await FetchData();
}
@@ -615,14 +615,14 @@
{
ToastService.ShowError("Something went wrong");
await AuditService.LogAsync(AuditActionType.Update, AuditEventType.Failure, AuditObjectType.Channel,
- _selectedChannel.Id.ToString(), LoggedUser?.Id, LoggedUser?.UserName, null,
+ _selectedChannel.Id.ToString(),
$"Failed to update channel. ChanId: {_selectedChannel.ChanId}");
}
else
{
ToastService.ShowSuccess("Channel updated successfully");
await AuditService.LogAsync(AuditActionType.Update, AuditEventType.Success, AuditObjectType.Channel,
- _selectedChannel.Id.ToString(), LoggedUser?.Id, LoggedUser?.UserName, null,
+ _selectedChannel.Id.ToString(),
$"Channel updated. ChanId: {_selectedChannel.ChanId}");
}
}
@@ -637,14 +637,14 @@
{
ToastService.ShowError("Something went wrong");
await AuditService.LogAsync(AuditActionType.Create, AuditEventType.Failure, AuditObjectType.LiquidityRule,
- _currentLiquidityRule.ChannelId.ToString(), LoggedUser?.Id, LoggedUser?.UserName, null,
+ _currentLiquidityRule.ChannelId.ToString(),
$"Failed to add liquidity rule for channel. ChannelId: {_currentLiquidityRule.ChannelId}");
}
else
{
ToastService.ShowSuccess("Liquidity rule added successfully");
await AuditService.LogAsync(AuditActionType.Create, AuditEventType.Success, AuditObjectType.LiquidityRule,
- _currentLiquidityRule.Id.ToString(), LoggedUser?.Id, LoggedUser?.UserName, null,
+ _currentLiquidityRule.Id.ToString(),
$"Liquidity rule created. ChannelId: {_currentLiquidityRule.ChannelId}, MinLocal: {_currentLiquidityRule.MinimumLocalBalance}%, MinRemote: {_currentLiquidityRule.MinimumRemoteBalance}%, Target: {_currentLiquidityRule.RebalanceTarget}%");
}
}
@@ -655,14 +655,14 @@
{
ToastService.ShowError("Something went wrong");
await AuditService.LogAsync(AuditActionType.Update, AuditEventType.Failure, AuditObjectType.LiquidityRule,
- _currentLiquidityRule.Id.ToString(), LoggedUser?.Id, LoggedUser?.UserName, null,
+ _currentLiquidityRule.Id.ToString(),
$"Failed to update liquidity rule. RuleId: {_currentLiquidityRule.Id}");
}
else
{
ToastService.ShowSuccess("Liquidity rule updated successfully");
await AuditService.LogAsync(AuditActionType.Update, AuditEventType.Success, AuditObjectType.LiquidityRule,
- _currentLiquidityRule.Id.ToString(), LoggedUser?.Id, LoggedUser?.UserName, null,
+ _currentLiquidityRule.Id.ToString(),
$"Liquidity rule updated. ChannelId: {_currentLiquidityRule.ChannelId}, MinLocal: {_currentLiquidityRule.MinimumLocalBalance}%, MinRemote: {_currentLiquidityRule.MinimumRemoteBalance}%, Target: {_currentLiquidityRule.RebalanceTarget}%");
}
}
@@ -735,14 +735,14 @@
{
ToastService.ShowError("Something went wrong");
await AuditService.LogAsync(actionType, AuditEventType.Failure, AuditObjectType.Channel,
- _selectedChannel.Id.ToString(), LoggedUser?.Id, LoggedUser?.UserName, null,
+ _selectedChannel.Id.ToString(),
$"Failed to {(enabledLiquidityMngmt ? "enable" : "disable")} liquidity management. ChanId: {_selectedChannel.ChanId}");
}
else
{
ToastService.ShowSuccess("Channel updated successfully");
await AuditService.LogAsync(actionType, AuditEventType.Success, AuditObjectType.Channel,
- _selectedChannel.Id.ToString(), LoggedUser?.Id, LoggedUser?.UserName, null,
+ _selectedChannel.Id.ToString(),
$"Liquidity management {(enabledLiquidityMngmt ? "enabled" : "disabled")}. ChanId: {_selectedChannel.ChanId}");
}
}
@@ -908,14 +908,14 @@
{
ToastService.ShowSuccess("Channel marked as closed");
await AuditService.LogAsync(AuditActionType.MarkAsClosed, AuditEventType.Success, AuditObjectType.Channel,
- contextItem.Id.ToString(), LoggedUser?.Id, LoggedUser?.UserName, null,
+ contextItem.Id.ToString(),
$"Channel marked as closed. ChanId: {contextItem.ChanId}");
}
else
{
ToastService.ShowError("Something went wrong: " + result.Item2);
await AuditService.LogAsync(AuditActionType.MarkAsClosed, AuditEventType.Failure, AuditObjectType.Channel,
- contextItem.Id.ToString(), LoggedUser?.Id, LoggedUser?.UserName, null,
+ contextItem.Id.ToString(),
$"Failed to mark channel as closed. ChanId: {contextItem.ChanId}. Error: {result.Item2}");
}
diff --git a/src/Pages/Nodes.razor b/src/Pages/Nodes.razor
index 0ab51323..ecbe8fe0 100644
--- a/src/Pages/Nodes.razor
+++ b/src/Pages/Nodes.razor
@@ -615,9 +615,6 @@
AuditEventType.Success,
AuditObjectType.Node,
arg.Item.Id.ToString(),
- LoggedUser?.Id,
- LoggedUser?.UserName,
- null,
new { Name = arg.Item.Name, PubKey = arg.Item.PubKey });
}
else
@@ -629,9 +626,6 @@
AuditEventType.Failure,
AuditObjectType.Node,
null,
- LoggedUser?.Id,
- LoggedUser?.UserName,
- null,
new { Name = arg.Item.Name, PubKey = arg.Item.PubKey, Error = addResult.Item2 });
}
}
@@ -656,9 +650,6 @@
AuditEventType.Success,
AuditObjectType.Node,
arg.Item.Id.ToString(),
- LoggedUser?.Id,
- LoggedUser?.UserName,
- null,
new { Name = arg.Item.Name, PubKey = arg.Item.PubKey });
}
else
@@ -669,9 +660,6 @@
AuditEventType.Failure,
AuditObjectType.Node,
arg.Item.Id.ToString(),
- LoggedUser?.Id,
- LoggedUser?.UserName,
- null,
new { Name = arg.Item.Name, PubKey = arg.Item.PubKey, Error = updateResult.Item2 });
}
}
@@ -722,9 +710,6 @@
AuditEventType.Success,
AuditObjectType.Node,
node.Id.ToString(),
- LoggedUser?.Id,
- LoggedUser?.UserName,
- null,
new { NodeName = node.Name, PubKey = node.PubKey });
_nodes = await NodeRepository.GetAll();
diff --git a/src/Pages/Wallets.razor b/src/Pages/Wallets.razor
index 5326dbd9..a4febb82 100644
--- a/src/Pages/Wallets.razor
+++ b/src/Pages/Wallets.razor
@@ -916,9 +916,6 @@ OnSubmit="TransferFundsHotWallet"/>
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();
}
@@ -930,9 +927,6 @@ OnSubmit="TransferFundsHotWallet"/>
AuditEventType.Failure,
AuditObjectType.Wallet,
null,
- LoggedUser?.Id,
- LoggedUser?.UserName,
- null,
new { Name = arg.Item.Name, Error = addResult.Item2 });
_wallets.Remove(arg.Item);
}
@@ -958,9 +952,6 @@ OnSubmit="TransferFundsHotWallet"/>
AuditEventType.Failure,
AuditObjectType.Wallet,
arg.Item.Id.ToString(),
- LoggedUser?.Id,
- LoggedUser?.UserName,
- null,
new { Name = arg.Item.Name, Error = message });
}
else
@@ -971,9 +962,6 @@ OnSubmit="TransferFundsHotWallet"/>
AuditEventType.Success,
AuditObjectType.Wallet,
arg.Item.Id.ToString(),
- LoggedUser?.Id,
- LoggedUser?.UserName,
- null,
new { Name = arg.Item.Name });
await GetData();
}
@@ -1011,9 +999,6 @@ OnSubmit="TransferFundsHotWallet"/>
AuditEventType.Success,
AuditObjectType.Wallet,
arg.Item.Id.ToString(),
- LoggedUser?.Id,
- LoggedUser?.UserName,
- null,
new { Name = arg.Item.Name, IsHotWallet = arg.Item.IsHotWallet });
}
else
@@ -1024,9 +1009,6 @@ OnSubmit="TransferFundsHotWallet"/>
AuditEventType.Failure,
AuditObjectType.Wallet,
arg.Item.Id.ToString(),
- LoggedUser?.Id,
- LoggedUser?.UserName,
- null,
new { Name = arg.Item.Name, Error = updateResult.Item2 });
}
@@ -1092,9 +1074,6 @@ OnSubmit="TransferFundsHotWallet"/>
AuditEventType.Success,
AuditObjectType.Wallet,
_selectedWallet.Id.ToString(),
- LoggedUser?.Id,
- LoggedUser?.UserName,
- null,
new { WalletName = _selectedWallet.Name, KeyId = _selectedWalletKey.Id });
}
else
@@ -1105,9 +1084,6 @@ OnSubmit="TransferFundsHotWallet"/>
AuditEventType.Failure,
AuditObjectType.Wallet,
_selectedWallet.Id.ToString(),
- LoggedUser?.Id,
- LoggedUser?.UserName,
- null,
new { WalletName = _selectedWallet.Name, KeyId = _selectedWalletKey.Id, Error = updateResult.Item2 });
}
}
@@ -1327,9 +1303,6 @@ OnSubmit="TransferFundsHotWallet"/>
AuditEventType.Success,
AuditObjectType.Wallet,
walletId.ToString(),
- LoggedUser?.Id,
- LoggedUser?.UserName,
- null,
new { Name = walletName });
}
else
@@ -1340,9 +1313,6 @@ OnSubmit="TransferFundsHotWallet"/>
AuditEventType.Failure,
AuditObjectType.Wallet,
walletId.ToString(),
- LoggedUser?.Id,
- LoggedUser?.UserName,
- null,
new { Name = walletName, Error = result.Item2 });
}
@@ -1428,9 +1398,6 @@ OnSubmit="TransferFundsHotWallet"/>
AuditEventType.Failure,
AuditObjectType.Wallet,
null,
- LoggedUser?.Id,
- LoggedUser?.UserName,
- null,
new { Name = _name, IsWatchOnly = _IsImportWalletModalWatchOnly, Error = result.Item2 });
return;
}
@@ -1445,9 +1412,6 @@ OnSubmit="TransferFundsHotWallet"/>
AuditEventType.Success,
AuditObjectType.Wallet,
null,
- LoggedUser?.Id,
- LoggedUser?.UserName,
- null,
new { Name = _name, IsWatchOnly = _IsImportWalletModalWatchOnly });
//Close modal
@@ -1609,9 +1573,6 @@ OnSubmit="TransferFundsHotWallet"/>
AuditEventType.Success,
AuditObjectType.Wallet,
_sourceTransferWallet?.Id.ToString(),
- LoggedUser?.Id,
- LoggedUser?.UserName,
- null,
new {
SourceWallet = _sourceWalletName,
TargetWallet = _targetWalletName,
@@ -1627,9 +1588,6 @@ OnSubmit="TransferFundsHotWallet"/>
AuditEventType.Failure,
AuditObjectType.Wallet,
_sourceTransferWallet?.Id.ToString(),
- LoggedUser?.Id,
- LoggedUser?.UserName,
- null,
new {
SourceWallet = _sourceWalletName,
TargetWallet = _targetWalletName,
@@ -1886,9 +1844,6 @@ OnSubmit="TransferFundsHotWallet"/>
AuditEventType.Failure,
AuditObjectType.UTXO,
utxo.Outpoint.ToString(),
- LoggedUser?.Id,
- LoggedUser?.UserName,
- null,
new { WalletId = _selectedWallet?.Id, Outpoint = utxo.Outpoint.ToString() });
return;
}
@@ -1898,9 +1853,6 @@ OnSubmit="TransferFundsHotWallet"/>
AuditEventType.Success,
AuditObjectType.UTXO,
utxo.Outpoint.ToString(),
- LoggedUser?.Id,
- LoggedUser?.UserName,
- null,
new { WalletId = _selectedWallet?.Id, Outpoint = utxo.Outpoint.ToString() });
// Updated the UI
diff --git a/src/Services/AuditService.cs b/src/Services/AuditService.cs
index 4a083d77..3e535e38 100644
--- a/src/Services/AuditService.cs
+++ b/src/Services/AuditService.cs
@@ -46,10 +46,31 @@ public async Task LogAsync(
AuditEventType eventType,
AuditObjectType objectAffected,
string? objectId = null,
- string? userId = null,
- string? username = null,
- string? ipAddress = null,
object? details = null)
+ {
+ var (userId, username, ipAddress) = ExtractContextInfo();
+ await LogInternalAsync(actionType, eventType, objectAffected, objectId, userId, username, ipAddress, details);
+ }
+
+ public async Task LogSystemAsync(
+ AuditActionType actionType,
+ AuditEventType eventType,
+ AuditObjectType objectAffected,
+ string? objectId = null,
+ object? details = null)
+ {
+ await LogInternalAsync(actionType, eventType, objectAffected, objectId, null, "SYSTEM", null, details);
+ }
+
+ private async Task LogInternalAsync(
+ AuditActionType actionType,
+ AuditEventType eventType,
+ AuditObjectType objectAffected,
+ string? objectId,
+ string? userId,
+ string? username,
+ string? ipAddress,
+ object? details)
{
try
{
@@ -92,44 +113,6 @@ public async Task LogAsync(
}
}
- public async Task LogAsync(
- AuditActionType actionType,
- AuditEventType eventType,
- AuditObjectType objectAffected,
- string? objectId = null,
- object? details = null)
- {
- var (userId, username, ipAddress) = ExtractContextInfo();
-
- await LogAsync(
- actionType,
- eventType,
- objectAffected,
- objectId,
- userId,
- username,
- ipAddress,
- details);
- }
-
- public async Task LogSystemAsync(
- AuditActionType actionType,
- AuditEventType eventType,
- AuditObjectType objectAffected,
- string? objectId = null,
- object? details = null)
- {
- await LogAsync(
- actionType,
- eventType,
- objectAffected,
- objectId,
- null, // No user ID for system operations
- "SYSTEM",
- null, // No IP address for system operations
- details);
- }
-
private (string? UserId, string? Username, string? IpAddress) ExtractContextInfo()
{
string? userId = null;
diff --git a/src/Services/IAuditService.cs b/src/Services/IAuditService.cs
index abd9879d..9cacc154 100644
--- a/src/Services/IAuditService.cs
+++ b/src/Services/IAuditService.cs
@@ -23,19 +23,6 @@ namespace NodeGuard.Services;
public interface IAuditService
{
- ///
- /// Log an audit event with all required fields
- ///
- Task LogAsync(
- AuditActionType actionType,
- AuditEventType eventType,
- AuditObjectType objectAffected,
- string? objectId = null,
- string? userId = null,
- string? username = null,
- string? ipAddress = null,
- object? details = null);
-
///
/// Log an audit event using HttpContext for user and IP extraction
///
diff --git a/src/Shared/NewSwapModal.razor b/src/Shared/NewSwapModal.razor
index bb98c50f..508d9958 100644
--- a/src/Shared/NewSwapModal.razor
+++ b/src/Shared/NewSwapModal.razor
@@ -314,9 +314,6 @@
AuditEventType.Success,
AuditObjectType.SwapOut,
response.Id,
- LoggedUser?.Id,
- LoggedUser?.UserName,
- null,
new
{
NodeId = _selectedNode.Id,
diff --git a/test/NodeGuard.Tests/Services/AuditServiceTests.cs b/test/NodeGuard.Tests/Services/AuditServiceTests.cs
index 53238834..7b9b4f46 100644
--- a/test/NodeGuard.Tests/Services/AuditServiceTests.cs
+++ b/test/NodeGuard.Tests/Services/AuditServiceTests.cs
@@ -93,55 +93,93 @@ private DefaultHttpContext CreateHttpContextWithUser(
return httpContext;
}
- #region LogAsync_FullParameters
+ #region LogAsync_AutoContext
[Fact]
- public async Task LogAsync_FullParameters_SuccessfulLogging_CallsRepositoryAndLogger()
+ public async Task LogAsync_AutoContext_WithAuthenticatedUser_ExtractsUserInfoFromClaims()
{
// Arrange
SetupSuccessfulRepository();
+ var httpContext = CreateHttpContextWithUser("user-123", "johndoe");
+ _httpContextAccessorMock.Setup(x => x.HttpContext).Returns(httpContext);
var service = CreateAuditService();
- var details = new { Operation = "Test", Value = 123 };
// Act
await service.LogAsync(
AuditActionType.Create,
AuditEventType.Success,
- AuditObjectType.User,
- "object-123",
- "user-456",
- "johndoe",
- "10.0.0.1",
- details);
+ AuditObjectType.Wallet,
+ "wallet-456",
+ new { Amount = 50000 });
// Assert
_auditLogRepositoryMock.Verify(
x => x.AddAsync(It.Is(log =>
- log.ActionType == AuditActionType.Create &&
- log.EventType == AuditEventType.Success &&
- log.ObjectAffected == AuditObjectType.User &&
- log.ObjectId == "object-123" &&
- log.UserId == "user-456" &&
+ log.UserId == "user-123" &&
log.Username == "johndoe" &&
- log.IpAddress == "10.0.0.1" &&
- log.Details != null)),
+ log.IpAddress == "192.168.1.100")),
Times.Once);
+ }
- _loggerMock.Verify(
- x => x.Log(
- LogLevel.Information,
- It.IsAny(),
- It.Is((v, t) => v.ToString()!.Contains("AUDIT:")),
- null,
- It.IsAny>()),
+ [Fact]
+ public async Task LogAsync_AutoContext_NoHttpContext_HandlesGracefully()
+ {
+ // Arrange
+ SetupSuccessfulRepository();
+ _httpContextAccessorMock.Setup(x => x.HttpContext).Returns((HttpContext?)null);
+ var service = CreateAuditService();
+
+ // Act
+ await service.LogAsync(
+ AuditActionType.Create,
+ AuditEventType.Success,
+ AuditObjectType.Wallet,
+ "wallet-456",
+ new { Amount = 50000 });
+
+ // Assert
+ _auditLogRepositoryMock.Verify(
+ x => x.AddAsync(It.Is(log =>
+ log.UserId == null &&
+ log.Username == null &&
+ log.IpAddress == null)),
Times.Once);
}
[Fact]
- public async Task LogAsync_FullParameters_RepositoryFails_LogsErrorButDoesNotThrow()
+ public async Task LogAsync_AutoContext_UnauthenticatedUser_HandlesGracefully()
+ {
+ // Arrange
+ SetupSuccessfulRepository();
+ var httpContext = new DefaultHttpContext();
+ httpContext.Connection.RemoteIpAddress = System.Net.IPAddress.Parse("192.168.1.200");
+ _httpContextAccessorMock.Setup(x => x.HttpContext).Returns(httpContext);
+ var service = CreateAuditService();
+
+ // Act
+ await service.LogAsync(
+ AuditActionType.Update,
+ AuditEventType.Success,
+ AuditObjectType.Channel,
+ "channel-789",
+ null);
+
+ // Assert
+ _auditLogRepositoryMock.Verify(
+ x => x.AddAsync(It.Is(log =>
+ log.UserId == null &&
+ log.Username == null &&
+ log.IpAddress == "192.168.1.200")),
+ Times.Once);
+ }
+
+ [Fact]
+ public async Task LogAsync_AutoContext_RepositoryFails_LogsErrorButDoesNotThrow()
{
// Arrange
SetupFailedRepository("Database connection failed");
+ var httpContext = CreateHttpContextWithUser();
+ _httpContextAccessorMock.Setup(x => x.HttpContext).Returns(httpContext);
var service = CreateAuditService();
// Act
@@ -166,9 +204,11 @@ public async Task LogAsync_FullParameters_RepositoryFails_LogsErrorButDoesNotThr
}
[Fact]
- public async Task LogAsync_FullParameters_ExceptionDuringLogging_CatchesAndLogsError()
+ public async Task LogAsync_AutoContext_ExceptionDuringLogging_CatchesAndLogsError()
{
// Arrange
+ var httpContext = CreateHttpContextWithUser();
+ _httpContextAccessorMock.Setup(x => x.HttpContext).Returns(httpContext);
var service = CreateAuditService();
_auditLogRepositoryMock
.Setup(x => x.AddAsync(It.IsAny()))
@@ -180,9 +220,6 @@ public async Task LogAsync_FullParameters_ExceptionDuringLogging_CatchesAndLogsE
AuditEventType.Success,
AuditObjectType.User,
"user-123",
- "user-456",
- "johndoe",
- "10.0.0.1",
new { Test = "data" });
// Assert
@@ -197,40 +234,71 @@ public async Task LogAsync_FullParameters_ExceptionDuringLogging_CatchesAndLogsE
It.IsAny>()),
Times.Once);
}
-
+
#endregion
- #region LogAsync_AutoContext
+ #region LogSystemAsync
[Fact]
- public async Task LogAsync_AutoContext_WithAuthenticatedUser_ExtractsUserInfoFromClaims()
+ public async Task LogSystemAsync_SuccessfulLogging_CreatesAuditLogWithSystemUser()
{
// Arrange
SetupSuccessfulRepository();
- var httpContext = CreateHttpContextWithUser("user-123", "johndoe");
- _httpContextAccessorMock.Setup(x => x.HttpContext).Returns(httpContext);
var service = CreateAuditService();
// Act
- await service.LogAsync(
+ await service.LogSystemAsync(
AuditActionType.Create,
AuditEventType.Success,
AuditObjectType.Wallet,
- "wallet-456",
- new { Amount = 50000 });
+ "wallet-123",
+ new { AutoGenerated = true });
// Assert
_auditLogRepositoryMock.Verify(
x => x.AddAsync(It.Is(log =>
- log.UserId == "user-123" &&
- log.Username == "johndoe" &&
- log.IpAddress == "192.168.1.100")),
+ log.ActionType == AuditActionType.Create &&
+ log.EventType == AuditEventType.Success &&
+ log.ObjectAffected == AuditObjectType.Wallet &&
+ log.ObjectId == "wallet-123" &&
+ log.UserId == null &&
+ log.Username == "SYSTEM" &&
+ log.IpAddress == null &&
+ log.Details != null)),
+ Times.Once);
+
+ _loggerMock.Verify(
+ x => x.Log(
+ LogLevel.Information,
+ It.IsAny(),
+ It.Is((v, t) => v.ToString()!.Contains("AUDIT:") && v.ToString()!.Contains("SYSTEM")),
+ null,
+ It.IsAny>()),
Times.Once);
}
-
- #endregion
- #region LogSystemAsync
+ [Fact]
+ public async Task LogSystemAsync_WithoutDetails_LogsSuccessfully()
+ {
+ // Arrange
+ SetupSuccessfulRepository();
+ var service = CreateAuditService();
+
+ // Act
+ await service.LogSystemAsync(
+ AuditActionType.Update,
+ AuditEventType.Success,
+ AuditObjectType.Channel,
+ "channel-456",
+ null);
+
+ // Assert
+ _auditLogRepositoryMock.Verify(
+ x => x.AddAsync(It.Is(log =>
+ log.Username == "SYSTEM" &&
+ log.Details == null)),
+ Times.Once);
+ }
[Fact]
public async Task LogSystemAsync_RepositoryFails_LogsErrorButDoesNotThrow()
@@ -259,5 +327,35 @@ public async Task LogSystemAsync_RepositoryFails_LogsErrorButDoesNotThrow()
Times.Once);
}
+ [Fact]
+ public async Task LogSystemAsync_ExceptionDuringLogging_CatchesAndLogsError()
+ {
+ // Arrange
+ var service = CreateAuditService();
+ _auditLogRepositoryMock
+ .Setup(x => x.AddAsync(It.IsAny()))
+ .ThrowsAsync(new InvalidOperationException("Database error"));
+
+ // Act
+ var act = async () => await service.LogSystemAsync(
+ AuditActionType.Delete,
+ AuditEventType.Success,
+ AuditObjectType.Node,
+ "node-789",
+ new { Reason = "Automated cleanup" });
+
+ // Assert
+ await act.Should().NotThrowAsync();
+
+ _loggerMock.Verify(
+ x => x.Log(
+ LogLevel.Error,
+ It.IsAny(),
+ It.Is((v, t) => v.ToString()!.Contains("Error logging audit event")),
+ It.IsAny(),
+ It.IsAny>()),
+ Times.Once);
+ }
+
#endregion
}