mirror of
https://github.com/aliasvault/aliasvault.git
synced 2026-04-04 23:05:19 -04:00
Show last 30 days instead of 72h for deletion requests (#1420)
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
namespace AliasVault.Admin.Main.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Model representing usernames with most account deletions in the last 72 hours.
|
||||
/// Model representing usernames with most account deletions in the last 30 days.
|
||||
/// </summary>
|
||||
public class RecentUsageAccountDeletions
|
||||
{
|
||||
@@ -18,9 +18,9 @@ public class RecentUsageAccountDeletions
|
||||
public string Username { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of account deletions for this username in the last 72 hours.
|
||||
/// Gets or sets the number of account deletions for this username in the last 30 days.
|
||||
/// </summary>
|
||||
public int DeletionCount72h { get; set; }
|
||||
public int DeletionCount30d { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the date when the most recent account with this username was registered.
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
namespace AliasVault.Admin.Main.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Model representing IP addresses with most account deletions in the last 72 hours.
|
||||
/// Model representing IP addresses with most account deletions in the last 30 days.
|
||||
/// </summary>
|
||||
public class RecentUsageDeletionsByIp
|
||||
{
|
||||
@@ -23,7 +23,7 @@ public class RecentUsageDeletionsByIp
|
||||
public string IpAddress { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of account deletions from this IP in the last 72 hours.
|
||||
/// Gets or sets the number of account deletions from this IP in the last 30 days.
|
||||
/// </summary>
|
||||
public int DeletionCount72h { get; set; }
|
||||
public int DeletionCount30d { get; set; }
|
||||
}
|
||||
|
||||
@@ -33,12 +33,12 @@ public class RecentUsageStatistics
|
||||
public List<RecentUsageMobileLogins> TopIpsByMobileLogins72h { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the list of IP addresses with most account deletions in the last 72 hours.
|
||||
/// Gets or sets the list of IP addresses with most account deletions in the last 30 days.
|
||||
/// </summary>
|
||||
public List<RecentUsageDeletionsByIp> TopIpsByDeletions72h { get; set; } = new();
|
||||
public List<RecentUsageDeletionsByIp> TopIpsByDeletions30d { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the list of usernames with most account deletions in the last 72 hours.
|
||||
/// Gets or sets the list of usernames with most account deletions in the last 30 days.
|
||||
/// </summary>
|
||||
public List<RecentUsageAccountDeletions> TopUsernamesByDeletions72h { get; set; } = new();
|
||||
public List<RecentUsageAccountDeletions> TopUsernamesByDeletions30d { get; set; } = new();
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
<div class="p-4 bg-white border border-gray-200 rounded-lg shadow-sm dark:border-gray-700 sm:p-6 dark:bg-gray-800">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<div>
|
||||
<h3 class="text-lg font-semibold text-gray-900 dark:text-white">Top Usernames by Account Deletions (Last 72h)</h3>
|
||||
<p class="text-sm text-gray-500 dark:text-gray-400">Usernames with the most account deletion events in the last 72 hours</p>
|
||||
<h3 class="text-lg font-semibold text-gray-900 dark:text-white">Top Usernames by Account Deletions (Last 30d)</h3>
|
||||
<p class="text-sm text-gray-500 dark:text-gray-400">Usernames with the most account deletion events in the last 30 days</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
@deletion.Username
|
||||
</a>
|
||||
</SortableTableColumn>
|
||||
<SortableTableColumn>@deletion.DeletionCount72h.ToString("N0")</SortableTableColumn>
|
||||
<SortableTableColumn>@deletion.DeletionCount30d.ToString("N0")</SortableTableColumn>
|
||||
<SortableTableColumn>
|
||||
@if (deletion.LastDeletionDate.HasValue)
|
||||
{
|
||||
@@ -47,7 +47,7 @@
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
||||
</svg>
|
||||
<h3 class="mt-2 text-sm font-medium text-gray-900 dark:text-white">No Recent Account Deletions</h3>
|
||||
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">No account deletions occurred in the last 72 hours.</p>
|
||||
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">No account deletions occurred in the last 30 days.</p>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
@@ -71,7 +71,7 @@
|
||||
private readonly List<TableColumn> _tableColumns = new()
|
||||
{
|
||||
new() { Title = "Username", PropertyName = "Username", Sortable = false },
|
||||
new() { Title = "Deletions (72h)", PropertyName = "DeletionCount72h", Sortable = false },
|
||||
new() { Title = "Deletions (30d)", PropertyName = "DeletionCount30d", Sortable = false },
|
||||
new() { Title = "Last Deletion", PropertyName = "LastDeletionDate", Sortable = false }
|
||||
};
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
<div class="p-4 bg-white border border-gray-200 rounded-lg shadow-sm dark:border-gray-700 sm:p-6 dark:bg-gray-800">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<div>
|
||||
<h3 class="text-lg font-semibold text-gray-900 dark:text-white">Top IP Addresses by Account Deletions (Last 72h)</h3>
|
||||
<p class="text-sm text-gray-500 dark:text-gray-400">IP addresses with the most account deletions in the last 72 hours (last octet anonymized)</p>
|
||||
<h3 class="text-lg font-semibold text-gray-900 dark:text-white">Top IP Addresses by Account Deletions (Last 30d)</h3>
|
||||
<p class="text-sm text-gray-500 dark:text-gray-400">IP addresses with the most account deletions in the last 30 days (last octet anonymized)</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
@ip.IpAddress
|
||||
</a>
|
||||
</SortableTableColumn>
|
||||
<SortableTableColumn>@ip.DeletionCount72h.ToString("N0")</SortableTableColumn>
|
||||
<SortableTableColumn>@ip.DeletionCount30d.ToString("N0")</SortableTableColumn>
|
||||
</SortableTableRow>
|
||||
}
|
||||
</SortableTable>
|
||||
@@ -37,7 +37,7 @@
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
||||
</svg>
|
||||
<h3 class="mt-2 text-sm font-medium text-gray-900 dark:text-white">No Recent Account Deletions</h3>
|
||||
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">No account deletions occurred in the last 72 hours.</p>
|
||||
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">No account deletions occurred in the last 30 days.</p>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
@@ -61,7 +61,7 @@
|
||||
private readonly List<TableColumn> _tableColumns = new()
|
||||
{
|
||||
new() { Title = "IP Range", PropertyName = "IpAddress", Sortable = false },
|
||||
new() { Title = "Deletions (72h)", PropertyName = "DeletionCount72h", Sortable = false }
|
||||
new() { Title = "Deletions (30d)", PropertyName = "DeletionCount30d", Sortable = false }
|
||||
};
|
||||
|
||||
private void HandlePageChanged(int page)
|
||||
|
||||
@@ -32,10 +32,10 @@
|
||||
<RecentUsageMobileLoginsTable Data="@_recentUsageStats?.TopIpsByMobileLogins72h" />
|
||||
|
||||
<!-- Top IP Addresses by Account Deletions ---->
|
||||
<RecentUsageDeletionsByIpTable Data="@_recentUsageStats?.TopIpsByDeletions72h" />
|
||||
<RecentUsageDeletionsByIpTable Data="@_recentUsageStats?.TopIpsByDeletions30d" />
|
||||
|
||||
<!-- Top Usernames by Account Deletions ---->
|
||||
<RecentUsageAccountDeletionsTable Data="@_recentUsageStats?.TopUsernamesByDeletions72h" />
|
||||
<RecentUsageAccountDeletionsTable Data="@_recentUsageStats?.TopUsernamesByDeletions30d" />
|
||||
</div>
|
||||
|
||||
@if (_loadingError)
|
||||
|
||||
@@ -116,8 +116,8 @@ public class StatisticsService
|
||||
GetTopUsersByEmails72hAsync().ContinueWith(t => stats.TopUsersByEmails72h = t.Result),
|
||||
GetTopIpsByRegistrations72hAsync().ContinueWith(t => stats.TopIpsByRegistrations72h = t.Result),
|
||||
GetTopIpsByMobileLogins72hAsync().ContinueWith(t => stats.TopIpsByMobileLogins72h = t.Result),
|
||||
GetTopIpsByDeletions72hAsync().ContinueWith(t => stats.TopIpsByDeletions72h = t.Result),
|
||||
GetTopUsernamesByDeletions72hAsync().ContinueWith(t => stats.TopUsernamesByDeletions72h = t.Result),
|
||||
GetTopIpsByDeletions30dAsync().ContinueWith(t => stats.TopIpsByDeletions30d = t.Result),
|
||||
GetTopUsernamesByDeletions30dAsync().ContinueWith(t => stats.TopUsernamesByDeletions30d = t.Result),
|
||||
};
|
||||
|
||||
await Task.WhenAll(tasks);
|
||||
@@ -611,13 +611,13 @@ public class StatisticsService
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the top 100 IP addresses by number of account deletions in the last 72 hours.
|
||||
/// Gets the top 100 IP addresses by number of account deletions in the last 30 days.
|
||||
/// </summary>
|
||||
/// <returns>List of top IP addresses by recent account deletions.</returns>
|
||||
private async Task<List<RecentUsageDeletionsByIp>> GetTopIpsByDeletions72hAsync()
|
||||
private async Task<List<RecentUsageDeletionsByIp>> GetTopIpsByDeletions30dAsync()
|
||||
{
|
||||
await using var context = await _contextFactory.CreateDbContextAsync();
|
||||
var cutoffDate = DateTime.UtcNow.AddHours(-72);
|
||||
var cutoffDate = DateTime.UtcNow.AddDays(-30);
|
||||
|
||||
// Get account deletions by IP from auth logs (using AccountDeletion event type)
|
||||
var topIps = await context.AuthLogs
|
||||
@@ -629,9 +629,9 @@ public class StatisticsService
|
||||
.Select(g => new
|
||||
{
|
||||
IpAddress = g.Key,
|
||||
DeletionCount72h = g.Count(),
|
||||
DeletionCount30d = g.Count(),
|
||||
})
|
||||
.OrderByDescending(ip => ip.DeletionCount72h)
|
||||
.OrderByDescending(ip => ip.DeletionCount30d)
|
||||
.Take(100)
|
||||
.ToListAsync();
|
||||
|
||||
@@ -639,18 +639,18 @@ public class StatisticsService
|
||||
{
|
||||
OriginalIpAddress = ip.IpAddress!,
|
||||
IpAddress = AnonymizeIpAddress(ip.IpAddress!),
|
||||
DeletionCount72h = ip.DeletionCount72h,
|
||||
DeletionCount30d = ip.DeletionCount30d,
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the top 100 usernames by number of account deletions in the last 72 hours.
|
||||
/// Gets the top 100 usernames by number of account deletions in the last 30 days.
|
||||
/// </summary>
|
||||
/// <returns>List of top usernames by recent account deletions.</returns>
|
||||
private async Task<List<RecentUsageAccountDeletions>> GetTopUsernamesByDeletions72hAsync()
|
||||
private async Task<List<RecentUsageAccountDeletions>> GetTopUsernamesByDeletions30dAsync()
|
||||
{
|
||||
await using var context = await _contextFactory.CreateDbContextAsync();
|
||||
var cutoffDate = DateTime.UtcNow.AddHours(-72);
|
||||
var cutoffDate = DateTime.UtcNow.AddDays(-30);
|
||||
|
||||
// Get account deletions by username from auth logs (using AccountDeletion event type)
|
||||
var topUsernames = await context.AuthLogs
|
||||
@@ -661,17 +661,17 @@ public class StatisticsService
|
||||
.Select(g => new
|
||||
{
|
||||
Username = g.Key,
|
||||
DeletionCount72h = g.Count(),
|
||||
DeletionCount30d = g.Count(),
|
||||
LastDeletionDate = g.Max(al => al.Timestamp),
|
||||
})
|
||||
.OrderByDescending(u => u.DeletionCount72h)
|
||||
.OrderByDescending(u => u.DeletionCount30d)
|
||||
.Take(100)
|
||||
.ToListAsync();
|
||||
|
||||
return topUsernames.Select(u => new RecentUsageAccountDeletions
|
||||
{
|
||||
Username = u.Username!,
|
||||
DeletionCount72h = u.DeletionCount72h,
|
||||
DeletionCount30d = u.DeletionCount30d,
|
||||
LastDeletionDate = u.LastDeletionDate,
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user