diff --git a/src/AliasVault.Admin/Main/Models/UserViewModel.cs b/src/AliasVault.Admin/Main/Models/UserViewModel.cs
index 6962209f4..5f98daf16 100644
--- a/src/AliasVault.Admin/Main/Models/UserViewModel.cs
+++ b/src/AliasVault.Admin/Main/Models/UserViewModel.cs
@@ -42,6 +42,11 @@ public class UserViewModel
///
public int VaultCount { get; set; }
+ ///
+ /// Gets or sets the credential count.
+ ///
+ public int CredentialCount { get; set; }
+
///
/// Gets or sets the email claim count.
///
diff --git a/src/AliasVault.Admin/Main/Pages/Users/Users.razor b/src/AliasVault.Admin/Main/Pages/Users/Users.razor
index 9750f57b5..32bafc874 100644
--- a/src/AliasVault.Admin/Main/Pages/Users/Users.razor
+++ b/src/AliasVault.Admin/Main/Pages/Users/Users.razor
@@ -7,7 +7,7 @@
+ Description="This page shows an overview of all registered users and the associated vaults.">
@@ -33,15 +33,19 @@ else
@user.CreatedAt.ToString("yyyy-MM-dd HH:mm")
@user.UserName
@user.VaultCount
+ @user.CredentialCount
@user.EmailClaimCount
@Math.Round((double)user.VaultStorageInKb / 1024, 1) MB
-
@user.LastVaultUpdate.ToString("yyyy-MM-dd HH:mm")
@if (user.Blocked)
{
}
+ @if (user.TwoFactorEnabled)
+ {
+
+ }
@@ -57,9 +61,9 @@ else
new TableColumn { Title = "Registered", PropertyName = "CreatedAt" },
new TableColumn { Title = "Username", PropertyName = "UserName" },
new TableColumn { Title = "# Vaults", PropertyName = "VaultCount" },
+ new TableColumn { Title = "# Credentials", PropertyName = "CredentialCount" },
new TableColumn { Title = "# Email claims", PropertyName = "EmailClaimCount" },
new TableColumn { Title = "Storage", PropertyName = "VaultStorageInKb" },
- new TableColumn { Title = "2FA", PropertyName = "TwoFactorEnabled" },
new TableColumn { Title = "LastVaultUpdate", PropertyName = "LastVaultUpdate" },
new TableColumn { Title = "Status", Sortable = false },
new TableColumn { Title = "Actions", Sortable = false},
@@ -72,7 +76,18 @@ else
private int TotalRecords { get; set; }
private string _searchTerm = string.Empty;
+
+ ///
+ /// The last search term.
+ ///
private string _lastSearchTerm = string.Empty;
+
+ ///
+ /// The page number before the search term was changed.
+ /// This is used to reset the page number back to the previous page when the search term is removed.
+ ///
+ private int _currentPageBeforeSearch = 1;
+
private string SearchTerm
{
get => _searchTerm;
@@ -119,8 +134,9 @@ else
if (SearchTerm.Length > 0)
{
// Reset page number back to 1 if the search term has changed.
- if (SearchTerm != _lastSearchTerm)
+ if (SearchTerm != _lastSearchTerm && CurrentPage != 1)
{
+ _currentPageBeforeSearch = CurrentPage;
CurrentPage = 1;
}
_lastSearchTerm = SearchTerm;
@@ -145,7 +161,9 @@ else
Vaults = u.Vaults.Select(v => new
{
v.FileSize,
- v.CreatedAt
+ v.CreatedAt,
+ v.RevisionNumber,
+ CredentialCount = v.CredentialsCount,
}),
EmailClaims = u.EmailClaims.Select(ec => new
{
@@ -162,6 +180,7 @@ else
Blocked = user.Blocked,
CreatedAt = user.CreatedAt,
VaultCount = user.Vaults.Count(),
+ CredentialCount = user.Vaults.OrderByDescending(x => x.RevisionNumber).First().CredentialCount,
EmailClaimCount = user.EmailClaims.Count(),
VaultStorageInKb = user.Vaults.Sum(x => x.FileSize),
LastVaultUpdate = user.Vaults.Any() ? user.Vaults.Max(x => x.CreatedAt) : user.CreatedAt,
@@ -199,6 +218,11 @@ else
? query.OrderBy(x => x.Vaults.Count)
: query.OrderByDescending(x => x.Vaults.Count);
break;
+ case "CredentialCount":
+ query = SortDirection == SortDirection.Ascending
+ ? query.OrderBy(x => x.Vaults.OrderByDescending(x => x.RevisionNumber).First().CredentialsCount)
+ : query.OrderByDescending(x => x.Vaults.OrderByDescending(x => x.RevisionNumber).First().CredentialsCount);
+ break;
case "EmailClaimCount":
query = SortDirection == SortDirection.Ascending
? query.OrderBy(x => x.EmailClaims.Count)
@@ -209,11 +233,6 @@ else
? query.OrderBy(x => x.Vaults.Sum(v => v.FileSize))
: query.OrderByDescending(x => x.Vaults.Sum(v => v.FileSize));
break;
- case "TwoFactorEnabled":
- query = SortDirection == SortDirection.Ascending
- ? query.OrderBy(x => x.TwoFactorEnabled)
- : query.OrderByDescending(x => x.TwoFactorEnabled);
- break;
case "LastVaultUpdate":
query = SortDirection == SortDirection.Ascending
? query.OrderBy(x => x.Vaults.Max(v => v.CreatedAt))