diff --git a/starsky/starsky.feature.geolookup/Services/GeoFileDownload.cs b/starsky/starsky.feature.geolookup/Services/GeoFileDownload.cs
index b1622a255a..9a7b0f2600 100644
--- a/starsky/starsky.feature.geolookup/Services/GeoFileDownload.cs
+++ b/starsky/starsky.feature.geolookup/Services/GeoFileDownload.cs
@@ -39,7 +39,7 @@ public async Task DownloadAsync()
RemoveFailedDownload();
CreateDependenciesFolder();
const string https = "https://";
- const string admin1codesasciiTxt = "admin1CodesASCII.txt";
+ const string admin1CodesasciiTxt = "admin1CodesASCII.txt";
if ( !_hostStorage.ExistFile(
Path.Combine(_appSettings.DependenciesFolder, CountryName + ".txt")) )
@@ -59,18 +59,18 @@ await _httpClientHelper.Download(https + MirrorUrl + CountryName + ".zip",
}
if ( !_hostStorage.ExistFile(
- Path.Combine(_appSettings.DependenciesFolder, admin1codesasciiTxt)) )
+ Path.Combine(_appSettings.DependenciesFolder, admin1CodesasciiTxt)) )
{
// code for the second administrative division,
// a county in the US, see file admin2Codes.txt; varchar(80)
var outputFile = Path.Combine(_appSettings.DependenciesFolder,
- admin1codesasciiTxt);
+ admin1CodesasciiTxt);
var baseResult = await _httpClientHelper.Download(https +
- BaseUrl + admin1codesasciiTxt, outputFile);
+ BaseUrl + admin1CodesasciiTxt, outputFile);
if ( !baseResult )
{
await _httpClientHelper.Download(https +
- MirrorUrl + admin1codesasciiTxt, outputFile);
+ MirrorUrl + admin1CodesasciiTxt, outputFile);
}
}
}
diff --git a/starsky/starsky.foundation.accountmanagement/Helpers/Pbkdf2Hasher.cs b/starsky/starsky.foundation.accountmanagement/Helpers/Pbkdf2Hasher.cs
index 21592ebd8a..61a088fe1d 100644
--- a/starsky/starsky.foundation.accountmanagement/Helpers/Pbkdf2Hasher.cs
+++ b/starsky/starsky.foundation.accountmanagement/Helpers/Pbkdf2Hasher.cs
@@ -5,41 +5,46 @@
using System.Security.Cryptography;
using Microsoft.AspNetCore.Cryptography.KeyDerivation;
-namespace starsky.foundation.accountmanagement.Helpers
+namespace starsky.foundation.accountmanagement.Helpers;
+
+public static class Pbkdf2Hasher
{
- public static class Pbkdf2Hasher
+ ///
+ /// Get secured hash passwords based on a salt
+ ///
+ /// password
+ /// to decrypt
+ /// more secure password
+ /// more secure password
+ /// hashed password
+ public static string ComputeHash(string password, byte[] salt, bool iteration100K = true, bool useSha256 = true)
{
- ///
- /// Get secured hash passwords based on a salt
- ///
- /// password
- /// to decrypt
- /// hased password
- public static string ComputeHash(string password, byte[] salt)
- {
- return Convert.ToBase64String(
- KeyDerivation.Pbkdf2(
- password: password,
- salt: salt,
- prf: KeyDerivationPrf.HMACSHA1,
- iterationCount: 100_000,
- numBytesRequested: 256 / 8
- )
- );
- }
+ // Use 100K iterations for new passwords, and 10K iterations for older stored hashes
+ var iterationCount = iteration100K ? 100_000 : 10000;
+ var hashType = useSha256 ? KeyDerivationPrf.HMACSHA256 : KeyDerivationPrf.HMACSHA1;
+
+ return Convert.ToBase64String(
+ KeyDerivation.Pbkdf2(
+ password: password,
+ salt: salt,
+ prf: hashType,
+ iterationCount: iterationCount,
+ numBytesRequested: 256 / 8
+ )
+ );
+ }
- ///
- /// Generate a random salt
- ///
- /// random salt
- public static byte[] GenerateRandomSalt()
- {
- byte[] salt = new byte[128 / 8];
+ ///
+ /// Generate a random salt
+ ///
+ /// random salt
+ public static byte[] GenerateRandomSalt()
+ {
+ var salt = new byte[128 / 8];
- using ( var rng = RandomNumberGenerator.Create() )
- rng.GetBytes(salt);
+ using var rng = RandomNumberGenerator.Create();
+ rng.GetBytes(salt);
- return salt;
- }
+ return salt;
}
}
diff --git a/starsky/starsky.foundation.accountmanagement/Interfaces/IUserManager.cs b/starsky/starsky.foundation.accountmanagement/Interfaces/IUserManager.cs
index 17496fa95d..013b945b84 100644
--- a/starsky/starsky.foundation.accountmanagement/Interfaces/IUserManager.cs
+++ b/starsky/starsky.foundation.accountmanagement/Interfaces/IUserManager.cs
@@ -3,101 +3,101 @@
using starsky.foundation.accountmanagement.Models;
using starsky.foundation.database.Models.Account;
-namespace starsky.foundation.accountmanagement.Interfaces
-{
- public enum SignUpResultError
- {
- CredentialTypeNotFound,
- NullString
- }
-
- public class SignUpResult
- {
- public User? User { get; }
- public bool Success { get; private set; }
- public SignUpResultError? Error { get; }
-
- public SignUpResult(User? user = null, bool success = false,
- SignUpResultError? error = null)
- {
- User = user;
- Success = success;
- Error = error;
- }
- }
+namespace starsky.foundation.accountmanagement.Interfaces;
- public enum ValidateResultError
- {
- CredentialTypeNotFound,
- CredentialNotFound,
- SecretNotValid,
- Lockout,
- UserNotFound
- }
+public enum SignUpResultError
+{
+ CredentialTypeNotFound,
+ NullString
+}
- public enum ChangeSecretResultError
+public class SignUpResult
+{
+ public SignUpResult(User? user = null, bool success = false,
+ SignUpResultError? error = null)
{
- CredentialTypeNotFound,
- CredentialNotFound
+ User = user;
+ Success = success;
+ Error = error;
}
- public class ChangeSecretResult
- {
- public bool Success { get; set; }
+ public User? User { get; }
+ public bool Success { get; private set; }
+ public SignUpResultError? Error { get; }
+}
- public ChangeSecretResultError? Error { get; set; }
+public enum ValidateResultError
+{
+ CredentialTypeNotFound,
+ CredentialNotFound,
+ SecretNotValid,
+ Lockout,
+ UserNotFound
+}
- public ChangeSecretResult(bool success = false, ChangeSecretResultError? error = null)
- {
- Success = success;
- Error = error;
- }
- }
+public enum ChangeSecretResultError
+{
+ CredentialTypeNotFound,
+ CredentialNotFound
+}
- public interface IUserManager
+public class ChangeSecretResult
+{
+ public ChangeSecretResult(bool success = false, ChangeSecretResultError? error = null)
{
- Task AllUsersAsync();
-
- ///
- /// Add a new user, including Roles and UserRoles
- ///
- /// Nice Name, default string.Empty
- /// default is: Email
- /// an email address, e.g. dont@mail.us
- /// Password
- /// result object
- Task SignUpAsync(string name, string credentialTypeCode,
- string? identifier, string? secret);
-
- void AddToRole(User user, string roleCode);
- void AddToRole(User user, Role role);
- void RemoveFromRole(User user, string roleCode);
- void RemoveFromRole(User user, Role role);
-
- ChangeSecretResult ChangeSecret(string credentialTypeCode, string? identifier,
- string secret);
-
- Task ValidateAsync(string credentialTypeCode,
- string? identifier, string secret);
-
- Task SignIn(HttpContext httpContext, User? user,
- bool isPersistent = false);
-
- void SignOut(HttpContext httpContext);
- int GetCurrentUserId(HttpContext httpContext);
- User? GetCurrentUser(HttpContext httpContext);
- User? GetUser(string credentialTypeCode, string identifier);
- Credential? GetCredentialsByUserId(int userId);
-
- Task RemoveUser(string credentialTypeCode,
- string identifier);
+ Success = success;
+ Error = error;
+ }
- User? Exist(string identifier);
+ public bool Success { get; set; }
- Task ExistAsync(int userTableId);
- Role? GetRole(string credentialTypeCode, string identifier);
+ public ChangeSecretResultError? Error { get; set; }
+}
- Task GetRoleAsync(int userId);
- bool PreflightValidate(string userName, string password, string confirmPassword);
- }
+public interface IUserManager
+{
+ Task AllUsersAsync();
+
+ ///
+ /// Add a new user, including Roles and UserRoles
+ ///
+ /// Nice Name, default string.Empty
+ /// default is: Email
+ /// an email address, e.g. dont@mail.us
+ /// Password
+ /// result object
+ Task SignUpAsync(string name, string credentialTypeCode,
+ string? identifier, string? secret);
+
+ void AddToRole(User user, string roleCode);
+ void AddToRole(User user, Role role);
+ void RemoveFromRole(User user, string roleCode);
+ void RemoveFromRole(User user, Role role);
+
+ ChangeSecretResult ChangeSecret(string credentialTypeCode, string? identifier,
+ string secret);
+
+ Task ValidateAsync(string credentialTypeCode,
+ string? identifier, string secret);
+
+ Task SignIn(HttpContext httpContext, User? user,
+ bool isPersistent = false);
+
+ void SignOut(HttpContext httpContext);
+ int GetCurrentUserId(HttpContext httpContext);
+ User? GetCurrentUser(HttpContext httpContext);
+ User? GetUser(string credentialTypeCode, string identifier);
+ Credential? GetCredentialsByUserId(int userId);
+
+ Task RemoveUser(string credentialTypeCode,
+ string identifier);
+
+ User? Exist(string identifier);
+
+ Task ExistAsync(int userTableId);
+ Role? GetRole(string credentialTypeCode, string identifier);
+
+ Task GetRoleAsync(int userId);
+ bool PreflightValidate(string userName, string password, string confirmPassword);
+ CredentialType? GetCachedCredentialType(string credentialTypeCode);
}
diff --git a/starsky/starsky.foundation.accountmanagement/Middleware/NoAccountLocalhostMiddleware.cs b/starsky/starsky.foundation.accountmanagement/Middleware/NoAccountLocalhostMiddleware.cs
index dcd898de4a..6cc827d47b 100644
--- a/starsky/starsky.foundation.accountmanagement/Middleware/NoAccountLocalhostMiddleware.cs
+++ b/starsky/starsky.foundation.accountmanagement/Middleware/NoAccountLocalhostMiddleware.cs
@@ -1,64 +1,93 @@
using System;
+using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using starsky.foundation.accountmanagement.Helpers;
using starsky.foundation.accountmanagement.Interfaces;
+using starsky.foundation.database.Models.Account;
using starsky.foundation.platform.Models;
// ReSharper disable once IdentifierTypo
[assembly: InternalsVisibleTo("starskytest")]
-namespace starsky.foundation.accountmanagement.Middleware
+
+namespace starsky.foundation.accountmanagement.Middleware;
+
+///
+/// Auto login when use is on localhost
+///
+public sealed class NoAccountMiddleware
{
///
- /// Auto login when use is on localhost
+ /// Default email address or Default User
///
- public sealed class NoAccountMiddleware
- {
- public NoAccountMiddleware(RequestDelegate next, AppSettings? appSettings = null)
- {
- _next = next;
- _appSettings = appSettings;
- }
+ internal const string Identifier = "mail@localhost";
- private readonly RequestDelegate _next;
- private readonly AppSettings? _appSettings;
+ private const string CredentialType = "email";
+ private readonly AppSettings? _appSettings;
- internal const string Identifier = "mail@localhost";
+ private readonly RequestDelegate _next;
- ///
- /// Enable: app__NoAccountLocalhost
- ///
- ///
- public async Task Invoke(HttpContext context)
- {
- var isHostAllowed = IsLocalhost.IsHostLocalHost(context.Connection.LocalIpAddress,
- context.Connection.RemoteIpAddress) || _appSettings?.DemoUnsafeDeleteStorageFolder == true;
+ public NoAccountMiddleware(RequestDelegate next, AppSettings? appSettings = null)
+ {
+ _next = next;
+ _appSettings = appSettings;
+ }
- var isApiCall = context.Request.Path.HasValue && ( context.Request.Path.Value.StartsWith("/api") ||
- context.Request.Path.Value.StartsWith("/realtime") );
+ ///
+ /// Enable: app__NoAccountLocalhost
+ ///
+ ///
+ public async Task Invoke(HttpContext context)
+ {
+ var isHostAllowed = IsLocalhost.IsHostLocalHost(context.Connection.LocalIpAddress,
+ context.Connection.RemoteIpAddress) ||
+ _appSettings?.DemoUnsafeDeleteStorageFolder == true;
- var isFromLogoutCall = context.Request.QueryString.HasValue &&
- context.Request.QueryString.Value!.Contains("fromLogout");
+ var isApiCall = context.Request.Path.HasValue &&
+ ( context.Request.Path.Value.StartsWith("/api") ||
+ context.Request.Path.Value.StartsWith("/realtime") );
- if ( isHostAllowed && context.User.Identity?.IsAuthenticated == false && !isApiCall && !isFromLogoutCall )
- {
- var userManager = ( IUserManager )context.RequestServices.GetRequiredService(typeof(IUserManager));
+ var isFromLogoutCall = context.Request.QueryString.HasValue &&
+ context.Request.QueryString.Value!.Contains("fromLogout");
- var user = userManager.GetUser("email", Identifier);
- if ( user == null )
- {
- var newPassword = Convert.ToBase64String(
- Pbkdf2Hasher.GenerateRandomSalt());
- await userManager.SignUpAsync(string.Empty,
- "email", Identifier, newPassword + newPassword);
- user = userManager.GetUser("email", Identifier);
- }
+ if ( isHostAllowed && context.User.Identity?.IsAuthenticated == false && !isApiCall &&
+ !isFromLogoutCall )
+ {
+ var userManager =
+ ( IUserManager )context.RequestServices.GetRequiredService(typeof(IUserManager));
+ var user = await CreateOrUpdateNewUsers(userManager);
+ await userManager.SignIn(context, user, true);
+ }
+
+ await _next.Invoke(context);
+ }
+
+ internal static async Task CreateOrUpdateNewUsers(IUserManager userManager)
+ {
+ var user = userManager.GetUser(CredentialType, Identifier);
+ if ( user == null )
+ {
+ var newPassword = Convert.ToBase64String(
+ Pbkdf2Hasher.GenerateRandomSalt());
+ await userManager.SignUpAsync(string.Empty,
+ CredentialType, Identifier, newPassword + newPassword);
+ user = userManager.GetUser(CredentialType, Identifier);
+ }
+ else
+ {
+ // Upgrade Path to phase out the old sha1 / iteration count
+ var credentialType = userManager.GetCachedCredentialType(CredentialType);
+ var credential =
+ user.Credentials!.FirstOrDefault(p => p.CredentialTypeId == credentialType?.Id);
+ if ( credential!.IterationCount == IterationCountType.Iterate100KSha256 ) return user;
- await userManager.SignIn(context, user, true);
- }
- await _next.Invoke(context);
+ var newPassword = Convert.ToBase64String(
+ Pbkdf2Hasher.GenerateRandomSalt());
+ userManager.ChangeSecret(CredentialType, Identifier, newPassword + newPassword);
}
+
+ return user;
}
}
diff --git a/starsky/starsky.foundation.accountmanagement/Services/UserManager.cs b/starsky/starsky.foundation.accountmanagement/Services/UserManager.cs
index 2552255262..d464c5f8f1 100644
--- a/starsky/starsky.foundation.accountmanagement/Services/UserManager.cs
+++ b/starsky/starsky.foundation.accountmanagement/Services/UserManager.cs
@@ -26,880 +26,807 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
[assembly: InternalsVisibleTo("starskytest")]
-namespace starsky.foundation.accountmanagement.Services
+
+namespace starsky.foundation.accountmanagement.Services;
+
+[Service(typeof(IUserManager), InjectionLifetime = InjectionLifetime.Scoped)]
+public sealed class UserManager : IUserManager
{
- [Service(typeof(IUserManager), InjectionLifetime = InjectionLifetime.Scoped)]
- public sealed class UserManager : IUserManager
+ public enum AppPermissions
+ {
+ AppSettingsWrite = 10
+ }
+
+
+ private const string AllUsersCacheKey = "UserManager_AllUsers";
+
+ private static readonly List AllPermissions = new()
+ {
+ AppPermissions.AppSettingsWrite
+ };
+
+ private readonly AppSettings _appSettings;
+ private readonly IMemoryCache? _cache;
+ private readonly ApplicationDbContext _dbContext;
+ private readonly IWebLogger _logger;
+
+ public UserManager(ApplicationDbContext dbContext, AppSettings appSettings, IWebLogger logger,
+ IMemoryCache? memoryCache = null)
{
- private readonly ApplicationDbContext _dbContext;
- private readonly IMemoryCache? _cache;
- private readonly AppSettings _appSettings;
- private readonly IWebLogger _logger;
+ _dbContext = dbContext;
+ _cache = memoryCache;
+ _appSettings = appSettings;
+ _logger = logger;
+ }
+
+ ///
+ /// Return the number of users in the database
+ ///
+ ///
+ public async Task AllUsersAsync()
+ {
+ if ( IsCacheEnabled() &&
+ _cache?.TryGetValue(AllUsersCacheKey, out var objectAllUsersResult) == true )
+ return new UserOverviewModel(( List? )objectAllUsersResult);
- public UserManager(ApplicationDbContext dbContext, AppSettings appSettings, IWebLogger logger,
- IMemoryCache? memoryCache = null)
+ try
{
- _dbContext = dbContext;
- _cache = memoryCache;
- _appSettings = appSettings;
- _logger = logger;
+ var allUsers = await _dbContext.Users.TagWith("AllUsersAsync").ToListAsync();
+ if ( IsCacheEnabled() )
+ _cache!.Set(AllUsersCacheKey, allUsers,
+ new TimeSpan(99, 0, 0));
+ return new UserOverviewModel(allUsers);
}
-
- private bool IsCacheEnabled()
+ catch ( RetryLimitExceededException exception )
{
- // || _appSettings?.AddMemoryCache == false > disabled
- return _cache != null;
+ _logger.LogError(exception,
+ "[User Manager] RetryLimitExceededException [catch-ed]");
}
- ///
- /// Add the roles 'User' and 'Administrator' to an empty database (and checks this list)
- ///
- /// List of roles in existingRoleNames
- private List AddDefaultRoles()
- {
- // User.HasClaim(ClaimTypes.Role, "Administrator") -- > p.Code
+ return new UserOverviewModel();
+ }
- var existingRoleNames = new List
- {
- AccountRoles.AppAccountRoles.User.ToString(),
- AccountRoles.AppAccountRoles.Administrator.ToString(),
- };
+ ///
+ /// Check if the user exist by username
+ ///
+ /// email
+ /// null or user
+ public User? Exist(string identifier)
+ {
+ var credential = _dbContext.Credentials.FirstOrDefault(p => p.Identifier == identifier);
+ if ( credential == null ) return null;
- var roles = new List();
- foreach ( var roleName in existingRoleNames )
- {
- var role = _dbContext.Roles
- .TagWith("AddDefaultRoles")
- .FirstOrDefault(p => p.Code != null && p.Code.ToLower().Equals(roleName.ToLower()));
-
- if ( role == null )
- {
- role = new Role
- {
- Code = roleName,
- Name = roleName,
- };
- _dbContext.Roles.Add(role);
- _dbContext.SaveChanges();
- }
-
- // Get the Int Ids from the database
- role = _dbContext.Roles.FirstOrDefault(p => p.Code != null && p.Code.ToLower().Equals(roleName.ToLower()));
-
- roles.Add(role!);
- }
+ var user = _dbContext.Users.FirstOrDefault(p => p.Id == credential.UserId);
+ return user;
+ }
- return roles;
- }
+ public async Task ExistAsync(int userTableId)
+ {
+ if ( !IsCacheEnabled() )
+ return await _dbContext.Users.FirstOrDefaultAsync(p => p.Id == userTableId);
- ///
- /// The default username is an email-address, this is added as default value to an empty database (and checks this list)
- ///
- /// the type, for example email
- ///
- internal async Task AddDefaultCredentialType(string credentialTypeCode)
+ var users = ( await AllUsersAsync() ).Users;
+ return users.Find(p => p.Id == userTableId);
+ }
+
+ ///
+ /// Add a new user, including Roles and UserRoles
+ ///
+ /// Nice Name, default string.Empty
+ /// default is: Email
+ /// an email address, e.g. dont@mail.us
+ /// Password
+ /// result object
+ public async Task SignUpAsync(string name,
+ string credentialTypeCode, string? identifier, string? secret)
+ {
+ var credentialType = await AddDefaultCredentialType(credentialTypeCode);
+ var roles = AddDefaultRoles();
+ AddDefaultPermissions();
+ AddDefaultRolePermissions();
+
+ if ( string.IsNullOrEmpty(identifier) || string.IsNullOrEmpty(secret) )
+ return new SignUpResult(success: false, error: SignUpResultError.NullString);
+
+ // The email is stored in the Credentials database
+ var user = Exist(identifier);
+ if ( user == null )
{
- var credentialType = _dbContext
- .CredentialTypes.TagWith("AddDefaultCredentialType")
- .FirstOrDefault(p => p.Code!.ToLower()
- .Equals(credentialTypeCode.ToLower()));
+ // Check if user not already exist
+ var createdDate = DateTime.UtcNow;
+ user = new User { Name = name, Created = createdDate };
- // When not exist add it
- if ( credentialType == null && credentialTypeCode.Equals("email", StringComparison.CurrentCultureIgnoreCase) )
- {
- credentialType = new CredentialType
- {
- Code = "email",
- Name = "email",
- Position = 1,
- Id = 1
- };
- await _dbContext.CredentialTypes.AddAsync(credentialType);
- await _dbContext.SaveChangesAsync();
- }
+ await _dbContext.Users.AddAsync(user);
+ await _dbContext.SaveChangesAsync();
+ await AddUserToCache(user);
- return credentialType;
+ // to get the id
+ user = await _dbContext.Users.FirstOrDefaultAsync(p => p.Created == createdDate);
+
+ if ( user == null ) throw new AggregateException("user should not be null");
}
+ // Add a user role based on a user id
+ var roleToAdd = roles.Find(p => p.Code == GetRoleAddToUser(identifier, user));
+ AddToRole(user, roleToAdd);
+
+ if ( credentialType == null )
+ return new SignUpResult(success: false,
+ error: SignUpResultError.CredentialTypeNotFound);
- private const string AllUsersCacheKey = "UserManager_AllUsers";
+ var credential =
+ await _dbContext.Credentials.FirstOrDefaultAsync(p => p.Identifier == identifier);
+ if ( credential != null ) return new SignUpResult(user, true);
- ///
- /// Return the number of users in the database
- ///
- ///
- public async Task AllUsersAsync()
+ // Check if credential not already exist
+ credential = new Credential
{
- if ( IsCacheEnabled() && _cache?.TryGetValue(AllUsersCacheKey, out var objectAllUsersResult) == true )
- {
- return new UserOverviewModel(( List? )objectAllUsersResult);
- }
+ UserId = user.Id,
+ CredentialTypeId = credentialType.Id,
+ Identifier = identifier,
+ IterationCount = IterationCountType.Iterate100KSha256
+ };
+ var salt = Pbkdf2Hasher.GenerateRandomSalt();
+ var hash = Pbkdf2Hasher.ComputeHash(secret, salt);
- try
- {
- var allUsers = await _dbContext.Users.TagWith("AllUsersAsync").ToListAsync();
- if ( IsCacheEnabled() )
- {
- _cache!.Set(AllUsersCacheKey, allUsers,
- new TimeSpan(99, 0, 0));
- }
- return new UserOverviewModel(allUsers);
- }
- catch ( RetryLimitExceededException exception )
- {
- _logger.LogError(exception,
- "[User Manager] RetryLimitExceededException [catch-ed]");
- }
+ credential.Secret = hash;
+ credential.Extra = Convert.ToBase64String(salt);
+ await _dbContext.Credentials.AddAsync(credential);
+ await _dbContext.SaveChangesAsync();
- return new UserOverviewModel();
- }
+ return new SignUpResult(user, true);
+ }
- ///
- /// Add one user to cached value
- ///
- internal async Task AddUserToCache(User user)
- {
- if ( !IsCacheEnabled() ) return;
- var allUsers = ( await AllUsersAsync() ).Users;
- var index = allUsers.Find(p => p.Id == user.Id);
- if ( allUsers.Exists(p => p.Id == user.Id) && index != null )
- {
- var indexOf = allUsers.IndexOf(index);
- allUsers[indexOf] = user;
- }
- else
- {
- allUsers.Add(user);
- }
- _cache!.Set(AllUsersCacheKey, allUsers,
- new TimeSpan(99, 0, 0));
- }
+ ///
+ /// Add a link between the user and the role (for example Admin)
+ ///
+ /// AccountUser object
+ /// RoleCode
+ public void AddToRole(User user, string roleCode)
+ {
+ var role = _dbContext.Roles.TagWith("AddToRole").FirstOrDefault(r => r.Code == roleCode);
- ///
- /// Remove one user from cache
- ///
- private async Task RemoveUserFromCacheAsync(User user)
- {
- if ( !IsCacheEnabled() ) return;
- var allUsers = ( await AllUsersAsync() ).Users;
- allUsers.Remove(user);
- _cache!.Set(AllUsersCacheKey, allUsers,
- new TimeSpan(99, 0, 0));
- }
+ if ( role == null ) return;
- ///
- /// Check if the user exist by username
- ///
- /// email
- /// null or user
- public User? Exist(string identifier)
- {
- var credential = _dbContext.Credentials.FirstOrDefault(p => p.Identifier == identifier);
- if ( credential == null ) return null;
+ AddToRole(user, role);
+ }
- var user = _dbContext.Users.FirstOrDefault(p => p.Id == credential.UserId);
- return user;
- }
+ ///
+ /// Add a link between the user and the role (for example Admin)
+ ///
+ /// AccountUser object
+ /// Role object
+ public void AddToRole(User user, Role? role)
+ {
+ var userRole =
+ _dbContext.UserRoles.FirstOrDefault(p => p.User != null && p.User.Id == user.Id);
- public async Task ExistAsync(int userTableId)
- {
- if ( !IsCacheEnabled() )
- {
- return await _dbContext.Users.FirstOrDefaultAsync(p => p.Id == userTableId);
- }
+ if ( userRole != null || role == null ) return;
- var users = ( await AllUsersAsync() ).Users;
- return users.Find(p => p.Id == userTableId);
- }
+ // Add a user role based on a user id
+ userRole = new UserRole { UserId = user.Id, RoleId = role.Id };
+ _dbContext.UserRoles.Add(userRole);
+ _dbContext.SaveChanges();
+ }
- ///
- /// AccountRegisterFirstRoleAdmin: Add first user as admin to avoid editing issues editing the storage location
- /// AccountRolesByEmailRegisterOverwrite: Overwrite the default role with a role from the config
- ///
- /// email address
- /// not any except it item itself
- /// RoleName in string
- internal string GetRoleAddToUser(string identifier, User user)
- {
- var roleToAddToUser = _appSettings.AccountRegisterDefaultRole.ToString();
+ public void RemoveFromRole(User user, string roleCode)
+ {
+ var role = _dbContext.Roles.TagWith("RemoveFromRole").FirstOrDefault(
+ r => string.Equals(r.Code, roleCode, StringComparison.OrdinalIgnoreCase));
- if ( _appSettings.AccountRegisterFirstRoleAdmin == true && !_dbContext.Users.Any(p => p != user) )
- {
- return AccountRoles.AppAccountRoles.Administrator.ToString();
- }
+ if ( role == null ) return;
- if ( _appSettings.AccountRolesByEmailRegisterOverwrite != null
- && _appSettings.AccountRolesByEmailRegisterOverwrite
- .TryGetValue(identifier, out var emailsForConfig) &&
- AccountRoles.GetAllRoles().Contains(emailsForConfig) )
- {
- return emailsForConfig;
- }
+ RemoveFromRole(user, role);
+ }
- return roleToAddToUser;
- }
+ public void RemoveFromRole(User user, Role role)
+ {
+ var userRole = _dbContext.UserRoles.Find(user.Id, role.Id);
- ///
- /// Add a new user, including Roles and UserRoles
- ///
- /// Nice Name, default string.Empty
- /// default is: Email
- /// an email address, e.g. dont@mail.us
- /// Password
- /// result object
- public async Task SignUpAsync(string name,
- string credentialTypeCode, string? identifier, string? secret)
- {
- var credentialType = await AddDefaultCredentialType(credentialTypeCode);
- var roles = AddDefaultRoles();
- AddDefaultPermissions();
- AddDefaultRolePermissions();
+ if ( userRole == null ) return;
- if ( string.IsNullOrEmpty(identifier) || string.IsNullOrEmpty(secret) )
- {
- return new SignUpResult(success: false, error: SignUpResultError.NullString);
- }
+ _dbContext.UserRoles.Remove(userRole);
+ _dbContext.SaveChanges();
+ }
- // The email is stored in the Credentials database
- var user = Exist(identifier);
- if ( user == null )
- {
- // Check if user not already exist
- var createdDate = DateTime.UtcNow;
- user = new User
- {
- Name = name,
- Created = createdDate
- };
-
- await _dbContext.Users.AddAsync(user);
- await _dbContext.SaveChangesAsync();
- await AddUserToCache(user);
-
- // to get the Id
- user = await _dbContext.Users.FirstOrDefaultAsync(p => p.Created == createdDate);
-
- if ( user == null ) throw new AggregateException("user should not be null");
- }
+ public ChangeSecretResult ChangeSecret(string credentialTypeCode, string? identifier,
+ string secret)
+ {
+ var credentialType = _dbContext.CredentialTypes.FirstOrDefault(
+ ct => ct.Code != null && ct.Code.ToLower().Equals(credentialTypeCode.ToLower()));
- // Add a user role based on a user id
- var roleToAdd = roles.Find(p => p.Code == GetRoleAddToUser(identifier, user));
- AddToRole(user, roleToAdd);
+ if ( credentialType == null )
+ return new ChangeSecretResult(false, ChangeSecretResultError.CredentialTypeNotFound);
- if ( credentialType == null )
- {
- return new SignUpResult(success: false, error: SignUpResultError.CredentialTypeNotFound);
- }
+ var credential = _dbContext.Credentials.TagWith("ChangeSecret").FirstOrDefault(
+ c => c.CredentialTypeId == credentialType.Id && c.Identifier == identifier);
- var credential = await _dbContext.Credentials.FirstOrDefaultAsync(p => p.Identifier == identifier);
- if ( credential != null ) return new SignUpResult(user: user, success: true);
+ if ( credential == null || identifier == null )
+ return new ChangeSecretResult(false, ChangeSecretResultError.CredentialNotFound);
- // Check if credential not already exist
- credential = new Credential
- {
- UserId = user.Id,
- CredentialTypeId = credentialType.Id,
- Identifier = identifier
- };
- byte[] salt = Pbkdf2Hasher.GenerateRandomSalt();
- string hash = Pbkdf2Hasher.ComputeHash(secret, salt);
+ var salt = Pbkdf2Hasher.GenerateRandomSalt();
+ var hash = Pbkdf2Hasher.ComputeHash(secret, salt);
- credential.Secret = hash;
- credential.Extra = Convert.ToBase64String(salt);
- await _dbContext.Credentials.AddAsync(credential);
- await _dbContext.SaveChangesAsync();
+ credential.IterationCount = IterationCountType.Iterate100KSha256;
+ credential.Secret = hash;
+ credential.Extra = Convert.ToBase64String(salt);
+ _dbContext.Credentials.Update(credential);
+ _dbContext.SaveChanges();
- return new SignUpResult(user: user, success: true);
- }
+ if ( IsCacheEnabled() )
+ _cache!.Set(CredentialCacheKey(credentialType, identifier),
+ credential, new TimeSpan(99, 0, 0));
- ///
- /// Add a link between the user and the role (for example Admin)
- ///
- /// AccountUser object
- /// RoleCode
- public void AddToRole(User user, string roleCode)
- {
- var role = _dbContext.Roles.TagWith("AddToRole").FirstOrDefault(r => r.Code == roleCode);
+ return new ChangeSecretResult(true);
+ }
- if ( role == null )
- {
- return;
- }
- AddToRole(user, role);
- }
+ ///
+ /// Get the CredentialType by the credentialTypeCode
+ ///
+ /// code to get the CredentialType
+ /// CredentialType
+ public CredentialType? GetCachedCredentialType(string credentialTypeCode)
+ {
+ var cacheKey = "credentialTypeCode_" + credentialTypeCode;
+ // Add caching for credentialType
+ if ( IsCacheEnabled() && _cache?.TryGetValue(cacheKey,
+ out var objectCredentialTypeCode) == true )
+ return ( CredentialType? )objectCredentialTypeCode;
- ///
- /// Add a link between the user and the role (for example Admin)
- ///
- /// AccountUser object
- /// Role object
- public void AddToRole(User user, Role? role)
- {
- var userRole = _dbContext.UserRoles.FirstOrDefault(p => p.User != null && p.User.Id == user.Id);
+ var credentialTypeSelect = _dbContext.CredentialTypes.AsNoTracking()
+ .TagWith("CredentialType").Where(
+ ct => ct.Code != null && ct.Code.ToLower().Equals(credentialTypeCode.ToLower()))
+ .Select(x => new { x.Id, x.Code, x.Name, x.Position }).FirstOrDefault();
- if ( userRole != null || role == null )
- {
- return;
- }
+ if ( credentialTypeSelect == null ) return null;
- // Add a user role based on a user id
- userRole = new UserRole
- {
- UserId = user.Id,
- RoleId = role.Id
- };
- _dbContext.UserRoles.Add(userRole);
- _dbContext.SaveChanges();
- }
- public void RemoveFromRole(User user, string roleCode)
+ var credentialType = new CredentialType
{
- var role = _dbContext.Roles.TagWith("RemoveFromRole").FirstOrDefault(
- r => string.Equals(r.Code, roleCode, StringComparison.OrdinalIgnoreCase));
-
- if ( role == null )
- {
- return;
- }
+ Id = credentialTypeSelect.Id,
+ Code = credentialTypeSelect.Code,
+ Name = credentialTypeSelect.Name,
+ Position = credentialTypeSelect.Position
+ };
- RemoveFromRole(user, role);
- }
+ if ( IsCacheEnabled() )
+ _cache!.Set(cacheKey, credentialType,
+ new TimeSpan(99, 0, 0));
+ return credentialType;
+ }
- public void RemoveFromRole(User user, Role role)
+ public bool PreflightValidate(string userName, string password, string confirmPassword)
+ {
+ var model = new RegisterViewModel
{
- var userRole = _dbContext.UserRoles.Find(user.Id, role.Id);
+ Email = userName, Password = password, ConfirmPassword = confirmPassword
+ };
- if ( userRole == null )
- {
- return;
- }
+ var context = new ValidationContext(model, null, null);
+ var results = new List();
+ return Validator.TryValidateObject(
+ model, context, results,
+ true
+ );
+ }
- _dbContext.UserRoles.Remove(userRole);
- _dbContext.SaveChanges();
- }
+ ///
+ /// Is the username and password combination correct
+ ///
+ /// default: email
+ /// email
+ /// password
+ /// status
+ public async Task ValidateAsync(string credentialTypeCode,
+ string? identifier, string secret)
+ {
+ // No Password
+ if ( string.IsNullOrWhiteSpace(secret) )
+ return new ValidateResult(success: false, error: ValidateResultError.SecretNotValid);
- public ChangeSecretResult ChangeSecret(string credentialTypeCode, string? identifier, string secret)
- {
- var credentialType = _dbContext.CredentialTypes.FirstOrDefault(
- ct => ct.Code != null && ct.Code.ToLower().Equals(credentialTypeCode.ToLower()));
+ var credentialType = GetCachedCredentialType(credentialTypeCode);
- if ( credentialType == null )
- {
- return new ChangeSecretResult(success: false, error: ChangeSecretResultError.CredentialTypeNotFound);
- }
+ if ( credentialType == null )
+ return new ValidateResult(success: false,
+ error: ValidateResultError.CredentialTypeNotFound);
- var credential = _dbContext.Credentials.TagWith("ChangeSecret").FirstOrDefault(
- c => c.CredentialTypeId == credentialType.Id && c.Identifier == identifier);
+ var credential = CachedCredential(credentialType, identifier);
- if ( credential == null || identifier == null )
- {
- return new ChangeSecretResult(success: false, error: ChangeSecretResultError.CredentialNotFound);
- }
+ if ( credential?.Extra == null )
+ return new ValidateResult(success: false,
+ error: ValidateResultError.CredentialNotFound);
- var salt = Pbkdf2Hasher.GenerateRandomSalt();
- var hash = Pbkdf2Hasher.ComputeHash(secret, salt);
+ var userData = ( await AllUsersAsync() ).Users.Find(p => p.Id == credential.UserId);
+ if ( userData == null )
+ return new ValidateResult(success: false, error: ValidateResultError.UserNotFound);
- credential.Secret = hash;
- credential.Extra = Convert.ToBase64String(salt);
- _dbContext.Credentials.Update(credential);
- _dbContext.SaveChanges();
+ if ( userData.LockoutEnabled && userData.LockoutEnd >= DateTime.UtcNow )
+ return new ValidateResult(success: false, error: ValidateResultError.Lockout);
- if ( IsCacheEnabled() )
- {
- _cache!.Set(CredentialCacheKey(credentialType, identifier),
- credential, new TimeSpan(99, 0, 0));
- }
+ // To compare the secret
+ var salt = Convert.FromBase64String(credential.Extra);
+ var iterationSecure = credential.IterationCount == IterationCountType.Iterate100KSha256;
- return new ChangeSecretResult(success: true);
- }
+ var hashedPassword =
+ Pbkdf2Hasher.ComputeHash(secret, salt, iterationSecure, iterationSecure);
- internal static string CredentialCacheKey(CredentialType credentialType, string? identifier)
+ if ( credential.Secret == hashedPassword )
{
- return "credential_" + credentialType.Id + "_" + identifier;
+ // to be removed in future releases
+ await TransformToNewIterationAsync(credential, salt, secret, credentialType);
+
+ return await ResetAndSuccess(userData.AccessFailedCount, credential.UserId, userData);
}
- ///
- /// Get the credential by cache data
- ///
- /// email
- /// the id
- /// Credential data object
- internal Credential? CachedCredential(CredentialType credentialType, string? identifier)
- {
- if ( string.IsNullOrEmpty(identifier) )
- {
- return null;
- }
+ return await SetLockIfFailedCountIsToHigh(credential.UserId);
+ }
- var key = CredentialCacheKey(credentialType, identifier);
+ public async Task SignIn(HttpContext httpContext, User? user, bool isPersistent = false)
+ {
+ if ( user == null ) return false;
+ var claims = GetUserClaims(user).ToList();
+ if ( claims.Count == 0 ) return false;
+
+ var identity =
+ new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
+ var principal = new ClaimsPrincipal(identity);
+
+ await httpContext.SignInAsync(
+ CookieAuthenticationDefaults.AuthenticationScheme,
+ principal,
+ new AuthenticationProperties { IsPersistent = isPersistent }
+ );
+
+ // Required in the direct context; when using a REST like call
+ httpContext.User = principal;
+ return true;
+ }
- // Add caching for credentialType
- if ( IsCacheEnabled() && _cache?.TryGetValue(key,
- out var objectCredentialTypeCode) == true )
+ ///
+ /// Remove user from database
+ ///
+ /// default: email
+ /// email address
+ /// status
+ public async Task RemoveUser(string credentialTypeCode,
+ string identifier)
+ {
+ var credentialType = GetCachedCredentialType(credentialTypeCode);
+ if ( credentialType == null )
+ return new ValidateResult
{
- return ( Credential? )objectCredentialTypeCode;
- }
+ Success = false, Error = ValidateResultError.CredentialTypeNotFound
+ };
- var credentialSelect = _dbContext.Credentials.AsNoTracking().TagWith("Credential").Where(
- c => c.CredentialTypeId == credentialType.Id && c.Identifier == identifier).Select(x => new
- {
- x.Id,
- x.UserId,
- x.CredentialTypeId,
- x.Secret,
- x.Extra
- }).FirstOrDefault();
-
- if ( credentialSelect == null )
- {
- return null;
- }
+ var credential = _dbContext.Credentials.FirstOrDefault(
+ c => c.CredentialTypeId == credentialType.Id && c.Identifier == identifier);
- var credential = new Credential
+ if ( credential == null )
+ return new ValidateResult
{
- Id = credentialSelect.Id,
- UserId = credentialSelect.UserId,
- CredentialTypeId = credentialSelect.CredentialTypeId,
- Secret = credentialSelect.Secret,
- Extra = credentialSelect.Extra,
+ Success = false, Error = ValidateResultError.CredentialNotFound
};
- if ( IsCacheEnabled() )
- {
- _cache!.Set(key, credential, new TimeSpan(99, 0, 0));
- }
-
- return credential;
- }
+ var user = await _dbContext.Users.FirstOrDefaultAsync(p => p.Id == credential.UserId);
+ var userRole =
+ await _dbContext.UserRoles.FirstOrDefaultAsync(p => p.UserId == credential.UserId);
- ///
- /// Get the CredentialType by the credentialTypeCode
- ///
- /// code to get the CredentialType
- /// CredentialType
- private CredentialType? CachedCredentialType(string credentialTypeCode)
- {
- var cacheKey = "credentialTypeCode_" + credentialTypeCode;
- // Add caching for credentialType
- if ( IsCacheEnabled() && _cache?.TryGetValue(cacheKey,
- out var objectCredentialTypeCode) == true )
+ if ( userRole == null || user == null )
+ return new ValidateResult
{
- return ( CredentialType? )objectCredentialTypeCode;
- }
+ Success = false, Error = ValidateResultError.CredentialNotFound
+ };
- var credentialTypeSelect = _dbContext.CredentialTypes.AsNoTracking().TagWith("CredentialType").Where(
- ct => ct.Code != null && ct.Code.ToLower().Equals(credentialTypeCode.ToLower())).Select(x => new
- {
- x.Id,
- x.Code,
- x.Name,
- x.Position
- }).FirstOrDefault();
+ _dbContext.Credentials.Remove(credential);
+ _dbContext.Users.Remove(user);
+ _dbContext.UserRoles.Remove(userRole);
+ await _dbContext.SaveChangesAsync();
- if ( credentialTypeSelect == null ) return null;
+ await RemoveUserFromCacheAsync(user);
- var credentialType = new CredentialType
- {
- Id = credentialTypeSelect.Id,
- Code = credentialTypeSelect.Code,
- Name = credentialTypeSelect.Name,
- Position = credentialTypeSelect.Position
- };
+ return new ValidateResult { Success = true };
+ }
- if ( IsCacheEnabled() )
- {
- _cache!.Set(cacheKey, credentialType,
- new TimeSpan(99, 0, 0));
- }
- return credentialType;
- }
+ public async void SignOut(HttpContext httpContext)
+ {
+ await httpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
+ }
- public bool PreflightValidate(string userName, string password, string confirmPassword)
- {
- var model = new RegisterViewModel
- {
- Email = userName,
- Password = password,
- ConfirmPassword = confirmPassword
- };
+ public int GetCurrentUserId(HttpContext httpContext)
+ {
+ if ( httpContext.User.Identity?.IsAuthenticated == false ) return -1;
- var context = new ValidationContext(model, null, null);
- var results = new List();
- return Validator.TryValidateObject(
- model, context, results,
- true
- );
- }
+ var claim =
+ httpContext.User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier);
- ///
- /// Is the username and password combination correct
- ///
- /// default: email
- /// email
- /// password
- /// status
- public async Task ValidateAsync(string credentialTypeCode,
- string? identifier, string secret)
- {
- var credentialType = CachedCredentialType(credentialTypeCode);
+ if ( claim == null ) return -1;
- if ( credentialType == null )
- {
- return new ValidateResult(success: false, error: ValidateResultError.CredentialTypeNotFound);
- }
+ if ( !int.TryParse(claim.Value, out var currentUserId) ) return -1;
- var credential = CachedCredential(credentialType, identifier);
+ return currentUserId;
+ }
- if ( credential?.Extra == null )
- {
- return new ValidateResult(success: false, error: ValidateResultError.CredentialNotFound);
- }
+ public User? GetCurrentUser(HttpContext httpContext)
+ {
+ var currentUserId = GetCurrentUserId(httpContext);
- // No Password
- if ( string.IsNullOrWhiteSpace(secret) )
- {
- return new ValidateResult(success: false, error: ValidateResultError.SecretNotValid);
- }
+ return currentUserId == -1 ? null : _dbContext.Users.Find(currentUserId);
+ }
- var userData = ( await AllUsersAsync() ).Users.Find(p => p.Id == credential.UserId);
- if ( userData == null )
- {
- return new ValidateResult(success: false, error: ValidateResultError.UserNotFound);
- }
+ public User? GetUser(string credentialTypeCode, string identifier)
+ {
+ var credentialType = GetCachedCredentialType(credentialTypeCode);
+ if ( credentialType == null ) return null;
+ var credential = _dbContext.Credentials.FirstOrDefault(
+ c => c.CredentialTypeId == credentialType.Id && c.Identifier == identifier);
+ if ( credential == null ) return null;
+ return _dbContext.Users.TagWith("GetUser").FirstOrDefault(p => p.Id == credential.UserId);
+ }
- if ( userData.LockoutEnabled && userData.LockoutEnd >= DateTime.UtcNow )
- {
- return new ValidateResult(success: false, error: ValidateResultError.Lockout);
- }
+ public Role? GetRole(string credentialTypeCode, string identifier)
+ {
+ var user = GetUser(credentialTypeCode, identifier);
+ if ( user == null ) return null;
+ var role = _dbContext.UserRoles.FirstOrDefault(p => p.User != null && p.User.Id == user.Id);
+ if ( role == null ) return new Role();
+ var roleId = role.RoleId;
+ return _dbContext.Roles.TagWith("GetRole").FirstOrDefault(p => p.Id == roleId);
+ }
- // To compare the secret
- byte[] salt = Convert.FromBase64String(credential.Extra);
- string hashedPassword = Pbkdf2Hasher.ComputeHash(secret, salt);
+ public async Task GetRoleAsync(int userId)
+ {
+ var role =
+ await _dbContext.UserRoles.FirstOrDefaultAsync(p =>
+ p.User != null && p.User.Id == userId);
+ if ( role == null ) return null;
+ var roleId = role.RoleId;
+ return _dbContext.Roles.TagWith("GetRole").FirstOrDefault(p => p.Id == roleId);
+ }
- if ( credential.Secret == hashedPassword )
- {
- return await ResetAndSuccess(userData.AccessFailedCount, credential.UserId, userData);
- }
+ public Credential? GetCredentialsByUserId(int userId)
+ {
+ return _dbContext.Credentials
+ .TagWith("GetCredentialsByUserId")
+ .FirstOrDefault(p => p.UserId == userId);
+ }
- return await SetLockIfFailedCountIsToHigh(credential.UserId);
- }
+ private bool IsCacheEnabled()
+ {
+ // || _appSettings?.AddMemoryCache == false > disabled
+ return _cache != null;
+ }
+
+ ///
+ /// Add the roles 'User' and 'Administrator' to an empty database (and checks this list)
+ ///
+ /// List of roles in existingRoleNames
+ private List AddDefaultRoles()
+ {
+ // User.HasClaim(ClaimTypes.Role, "Administrator") -- > p.Code
- internal async Task ResetAndSuccess(int accessFailedCount, int userId, User? userData)
+ var existingRoleNames = new List
{
- if ( accessFailedCount <= 0 )
- {
- return new ValidateResult(userData, true);
- }
+ AccountRoles.AppAccountRoles.User.ToString(),
+ AccountRoles.AppAccountRoles.Administrator.ToString()
+ };
- userData = await _dbContext.Users.FindAsync(userId);
- if ( userData == null )
+ var roles = new List();
+ foreach ( var roleName in existingRoleNames )
+ {
+ var role = _dbContext.Roles
+ .TagWith("AddDefaultRoles")
+ .FirstOrDefault(p => p.Code != null && p.Code.ToLower().Equals(roleName.ToLower()));
+
+ if ( role == null )
{
- return new ValidateResult(success: false,
- error: ValidateResultError.UserNotFound);
+ role = new Role { Code = roleName, Name = roleName };
+ _dbContext.Roles.Add(role);
+ _dbContext.SaveChanges();
}
- userData.LockoutEnabled = false;
- userData.AccessFailedCount = 0;
- userData.LockoutEnd = DateTime.MinValue;
- await _dbContext.SaveChangesAsync();
- await AddUserToCache(userData);
+ // Get the Int Ids from the database
+ role = _dbContext.Roles.FirstOrDefault(p =>
+ p.Code != null && p.Code.ToLower().Equals(roleName.ToLower()));
- return new ValidateResult(userData, true);
+ roles.Add(role!);
}
- internal async Task SetLockIfFailedCountIsToHigh(int userId)
+ return roles;
+ }
+
+ ///
+ /// The default username is an email-address, this is added as default value to an empty database
+ /// (and checks this list)
+ ///
+ /// the type, for example email
+ ///
+ internal async Task AddDefaultCredentialType(string credentialTypeCode)
+ {
+ var credentialType = _dbContext
+ .CredentialTypes.TagWith("AddDefaultCredentialType")
+ .FirstOrDefault(p => p.Code!.ToLower()
+ .Equals(credentialTypeCode.ToLower()));
+
+ // When not exist add it
+ if ( credentialType == null &&
+ credentialTypeCode.Equals("email", StringComparison.CurrentCultureIgnoreCase) )
{
- var errorReason = ValidateResultError.SecretNotValid;
- var userData = await _dbContext.Users.FindAsync(userId);
- if ( userData == null )
+ credentialType = new CredentialType
{
- return new ValidateResult(success: false,
- error: ValidateResultError.UserNotFound);
- }
- userData.AccessFailedCount++;
- if ( userData.AccessFailedCount >= 3 )
- {
- userData.LockoutEnabled = true;
- userData.AccessFailedCount = 0;
- errorReason = ValidateResultError.Lockout;
- userData.LockoutEnd = DateTime.UtcNow.AddHours(1);
- }
+ Code = "email", Name = "email", Position = 1, Id = 1
+ };
+ await _dbContext.CredentialTypes.AddAsync(credentialType);
await _dbContext.SaveChangesAsync();
- await AddUserToCache(userData);
- return new ValidateResult(success: false, error: errorReason);
}
- public async Task SignIn(HttpContext httpContext, User? user, bool isPersistent = false)
- {
- if ( user == null )
- {
- return false;
- }
- var claims = GetUserClaims(user).ToList();
- if ( claims.Count == 0 )
- {
- return false;
- }
-
- ClaimsIdentity identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
- ClaimsPrincipal principal = new ClaimsPrincipal(identity);
-
- await httpContext.SignInAsync(
- CookieAuthenticationDefaults.AuthenticationScheme,
- principal,
- new AuthenticationProperties() { IsPersistent = isPersistent }
- );
+ return credentialType;
+ }
- // Required in the direct context; when using a REST like call
- httpContext.User = principal;
- return true;
+ ///
+ /// Add one user to cached value
+ ///
+ internal async Task AddUserToCache(User user)
+ {
+ if ( !IsCacheEnabled() ) return;
+ var allUsers = ( await AllUsersAsync() ).Users;
+ var index = allUsers.Find(p => p.Id == user.Id);
+ if ( allUsers.Exists(p => p.Id == user.Id) && index != null )
+ {
+ var indexOf = allUsers.IndexOf(index);
+ allUsers[indexOf] = user;
}
-
- ///
- /// Remove user from database
- ///
- /// default: email
- /// email address
- /// status
- public async Task RemoveUser(string credentialTypeCode,
- string identifier)
+ else
{
- var credentialType = CachedCredentialType(credentialTypeCode);
- if ( credentialType == null )
- {
- return new ValidateResult { Success = false, Error = ValidateResultError.CredentialTypeNotFound };
- }
+ allUsers.Add(user);
+ }
- var credential = _dbContext.Credentials.FirstOrDefault(
- c => c.CredentialTypeId == credentialType.Id && c.Identifier == identifier);
+ _cache!.Set(AllUsersCacheKey, allUsers,
+ new TimeSpan(99, 0, 0));
+ }
- if ( credential == null )
- {
- return new ValidateResult
- {
- Success = false,
- Error = ValidateResultError.CredentialNotFound
- };
- }
+ ///
+ /// Remove one user from cache
+ ///
+ private async Task RemoveUserFromCacheAsync(User user)
+ {
+ if ( !IsCacheEnabled() ) return;
+ var allUsers = ( await AllUsersAsync() ).Users;
+ allUsers.Remove(user);
+ _cache!.Set(AllUsersCacheKey, allUsers,
+ new TimeSpan(99, 0, 0));
+ }
- var user = await _dbContext.Users.FirstOrDefaultAsync(p => p.Id == credential.UserId);
+ ///
+ /// AccountRegisterFirstRoleAdmin: Add first user as admin to avoid editing issues editing the
+ /// storage location
+ /// AccountRolesByEmailRegisterOverwrite: Overwrite the default role with a role from the config
+ ///
+ /// email address
+ /// not any except it item itself
+ /// RoleName in string
+ internal string GetRoleAddToUser(string identifier, User user)
+ {
+ var roleToAddToUser = _appSettings.AccountRegisterDefaultRole.ToString();
- var userRole = await _dbContext.UserRoles.FirstOrDefaultAsync(p => p.UserId == credential.UserId);
+ if ( _appSettings.AccountRegisterFirstRoleAdmin == true &&
+ !_dbContext.Users.Any(p => p != user) )
+ return AccountRoles.AppAccountRoles.Administrator.ToString();
- if ( userRole == null || user == null )
- {
- return new ValidateResult
- {
- Success = false,
- Error = ValidateResultError.CredentialNotFound
- };
- }
+ if ( _appSettings.AccountRolesByEmailRegisterOverwrite != null
+ && _appSettings.AccountRolesByEmailRegisterOverwrite
+ .TryGetValue(identifier, out var emailsForConfig) &&
+ AccountRoles.GetAllRoles().Contains(emailsForConfig) )
+ return emailsForConfig;
- _dbContext.Credentials.Remove(credential);
- _dbContext.Users.Remove(user);
- _dbContext.UserRoles.Remove(userRole);
- await _dbContext.SaveChangesAsync();
+ return roleToAddToUser;
+ }
- await RemoveUserFromCacheAsync(user);
+ internal static string CredentialCacheKey(CredentialType credentialType, string? identifier)
+ {
+ return "credential_" + credentialType.Id + "_" + identifier;
+ }
- return new ValidateResult { Success = true };
- }
+ ///
+ /// Get the credential by cache data
+ ///
+ /// email
+ /// the id
+ /// Credential data object
+ internal Credential? CachedCredential(CredentialType credentialType, string? identifier)
+ {
+ if ( string.IsNullOrEmpty(identifier) ) return null;
+
+ var key = CredentialCacheKey(credentialType, identifier);
+
+ // Add caching for credentialType
+ if ( IsCacheEnabled() && _cache?.TryGetValue(key,
+ out var objectCredentialTypeCode) == true )
+ return ( Credential? )objectCredentialTypeCode;
+
+ var credentialSelect = _dbContext.Credentials.AsNoTracking().TagWith("Credential").Where(
+ c => c.CredentialTypeId == credentialType.Id && c.Identifier == identifier).Select(x =>
+ new
+ {
+ x.Id,
+ x.UserId,
+ x.CredentialTypeId,
+ x.Secret,
+ x.Extra,
+ x.IterationCount,
+ x.Identifier
+ }).FirstOrDefault();
+
+ if ( credentialSelect == null ) return null;
+
+ var credential = new Credential
+ {
+ Id = credentialSelect.Id,
+ UserId = credentialSelect.UserId,
+ CredentialTypeId = credentialSelect.CredentialTypeId,
+ Secret = credentialSelect.Secret,
+ Extra = credentialSelect.Extra,
+ IterationCount = credentialSelect.IterationCount,
+ Identifier = credentialSelect.Identifier
+ };
- public async void SignOut(HttpContext httpContext)
- {
- await httpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
- }
+ if ( IsCacheEnabled() ) _cache!.Set(key, credential, new TimeSpan(99, 0, 0));
- public int GetCurrentUserId(HttpContext httpContext)
- {
- if ( httpContext.User.Identity?.IsAuthenticated == false )
- {
- return -1;
- }
+ return credential;
+ }
- var claim = httpContext.User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier);
+ public async Task TransformToNewIterationAsync(Credential credential, byte[] salt,
+ string secret,
+ CredentialType credentialType)
+ {
+ if ( credential.IterationCount == IterationCountType.Iterate100KSha256 ) return;
- if ( claim == null )
- {
- return -1;
- }
+ credential.IterationCount = IterationCountType.Iterate100KSha256;
+ credential.Secret = Pbkdf2Hasher.ComputeHash(secret, salt);
+ _dbContext.Credentials.Update(credential);
+ await _dbContext.SaveChangesAsync();
+ _cache?.Remove(CredentialCacheKey(credentialType, credential.Identifier));
+ }
- if ( !int.TryParse(claim.Value, out var currentUserId) )
- {
- return -1;
- }
+ internal async Task ResetAndSuccess(int accessFailedCount, int userId,
+ User? userData)
+ {
+ if ( accessFailedCount <= 0 ) return new ValidateResult(userData, true);
- return currentUserId;
- }
+ userData = await _dbContext.Users.FindAsync(userId);
+ if ( userData == null )
+ return new ValidateResult(success: false,
+ error: ValidateResultError.UserNotFound);
- public User? GetCurrentUser(HttpContext httpContext)
- {
- var currentUserId = GetCurrentUserId(httpContext);
+ userData.LockoutEnabled = false;
+ userData.AccessFailedCount = 0;
+ userData.LockoutEnd = DateTime.MinValue;
+ await _dbContext.SaveChangesAsync();
+ await AddUserToCache(userData);
- return currentUserId == -1 ? null : _dbContext.Users.Find(currentUserId);
- }
+ return new ValidateResult(userData, true);
+ }
- public User? GetUser(string credentialTypeCode, string identifier)
- {
- var credentialType = CachedCredentialType(credentialTypeCode);
- if ( credentialType == null ) return null;
- var credential = _dbContext.Credentials.FirstOrDefault(
- c => c.CredentialTypeId == credentialType.Id && c.Identifier == identifier);
- if ( credential == null ) return null;
- return _dbContext.Users.TagWith("GetUser").FirstOrDefault(p => p.Id == credential.UserId);
+ internal async Task SetLockIfFailedCountIsToHigh(int userId)
+ {
+ var errorReason = ValidateResultError.SecretNotValid;
+ var userData = await _dbContext.Users.FindAsync(userId);
+ if ( userData == null )
+ return new ValidateResult(success: false,
+ error: ValidateResultError.UserNotFound);
+ userData.AccessFailedCount++;
+ if ( userData.AccessFailedCount >= 3 )
+ {
+ userData.LockoutEnabled = true;
+ userData.AccessFailedCount = 0;
+ errorReason = ValidateResultError.Lockout;
+ userData.LockoutEnd = DateTime.UtcNow.AddHours(1);
}
- public Role? GetRole(string credentialTypeCode, string identifier)
- {
- var user = GetUser(credentialTypeCode, identifier);
- if ( user == null )
- {
- return null;
- }
- var role = _dbContext.UserRoles.FirstOrDefault(p => p.User != null && p.User.Id == user.Id);
- if ( role == null ) return new Role();
- var roleId = role.RoleId;
- return _dbContext.Roles.TagWith("GetRole").FirstOrDefault(p => p.Id == roleId);
- }
+ await _dbContext.SaveChangesAsync();
+ await AddUserToCache(userData);
+ return new ValidateResult(success: false, error: errorReason);
+ }
- public async Task GetRoleAsync(int userId)
- {
- var role = await _dbContext.UserRoles.FirstOrDefaultAsync(p => p.User != null && p.User.Id == userId);
- if ( role == null ) return null;
- var roleId = role.RoleId;
- return _dbContext.Roles.TagWith("GetRole").FirstOrDefault(p => p.Id == roleId);
- }
+ internal IEnumerable GetUserClaims(User? user)
+ {
+ if ( user == null || user.Id == 0 ) return new List();
- public Credential? GetCredentialsByUserId(int userId)
- {
- return _dbContext.Credentials
- .TagWith("GetCredentialsByUserId")
- .FirstOrDefault(p => p.UserId == userId);
- }
+ var email =
+ user.Credentials?.FirstOrDefault(p =>
+ !string.IsNullOrEmpty(p.Identifier))?.Identifier;
- internal IEnumerable GetUserClaims(User? user)
+ var claims = new List
{
- if ( user == null || user.Id == 0 )
- {
- return new List();
- }
-
- var email =
- user.Credentials?.FirstOrDefault(p =>
- !string.IsNullOrEmpty(p.Identifier))?.Identifier;
+ new(ClaimTypes.NameIdentifier, user.Id.ToString()),
+ new(ClaimTypes.Name, user.Name ?? string.Empty),
+ new(ClaimTypes.Email, email ?? string.Empty)
+ };
- var claims = new List
- {
- new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
- new Claim(ClaimTypes.Name, user.Name ?? string.Empty),
- new Claim(ClaimTypes.Email, email ?? string.Empty),
- };
+ claims.AddRange(GetUserRoleClaims(user));
+ return claims;
+ }
- claims.AddRange(GetUserRoleClaims(user));
- return claims;
- }
+ private List GetUserRoleClaims(User user)
+ {
+ var claims = new List();
+ IEnumerable roleIds = _dbContext.UserRoles.TagWith("GetUserRoleClaims").Where(
+ ur => ur.UserId == user.Id).Select(ur => ur.RoleId).ToList();
- private List GetUserRoleClaims(User user)
+ foreach ( var roleId in roleIds )
{
- var claims = new List();
- IEnumerable roleIds = _dbContext.UserRoles.TagWith("GetUserRoleClaims").Where(
- ur => ur.UserId == user.Id).Select(ur => ur.RoleId).ToList();
-
- foreach ( var roleId in roleIds )
- {
- var role = _dbContext.Roles.Find(roleId);
- if ( role?.Code == null )
- {
- continue;
- }
- claims.Add(new Claim(ClaimTypes.Role, role.Code));
- claims.AddRange(GetUserPermissionClaims(role));
- }
- return claims;
+ var role = _dbContext.Roles.Find(roleId);
+ if ( role?.Code == null ) continue;
+ claims.Add(new Claim(ClaimTypes.Role, role.Code));
+ claims.AddRange(GetUserPermissionClaims(role));
}
- internal IEnumerable GetUserPermissionClaims(Role role)
- {
- List claims = new List();
- var rolePermissions = _dbContext.RolePermissions.Where(
- rp => rp.RoleId == role.Id);
- IEnumerable permissionIds = rolePermissions.Select(rp => rp.PermissionId).ToList();
+ return claims;
+ }
- foreach ( var permissionId in permissionIds )
- {
- var permission = _dbContext.Permissions.Find(permissionId);
- if ( permission?.Code == null )
- {
- continue;
- }
- claims.Add(new Claim("Permission", permission.Code!));
- }
+ internal IEnumerable GetUserPermissionClaims(Role role)
+ {
+ var claims = new List();
+ var rolePermissions = _dbContext.RolePermissions.Where(
+ rp => rp.RoleId == role.Id);
+ IEnumerable permissionIds = rolePermissions.Select(rp => rp.PermissionId).ToList();
- return claims;
+ foreach ( var permissionId in permissionIds )
+ {
+ var permission = _dbContext.Permissions.Find(permissionId);
+ if ( permission?.Code == null ) continue;
+ claims.Add(new Claim("Permission", permission.Code!));
}
- public enum AppPermissions
+ return claims;
+ }
+
+ private void AddDefaultPermissions()
+ {
+ foreach ( var permissionEnum in AllPermissions )
{
- AppSettingsWrite = 10,
+ var permission =
+ _dbContext.Permissions.FirstOrDefault(p => p.Code == permissionEnum.ToString());
+
+ if ( permission != null ) continue;
+
+ permission = new Permission
+ {
+ Name = permissionEnum.ToString(),
+ Code = permissionEnum.ToString(),
+ Position = ( int )permissionEnum
+ };
+ _dbContext.Permissions.Add(permission);
+ _dbContext.SaveChanges();
}
+ }
- private static readonly List AllPermissions = new List
+ private void AddDefaultRolePermissions()
+ {
+ var existingRolePermissions = new List>
{
- AppPermissions.AppSettingsWrite,
+ new(
+ AccountRoles.AppAccountRoles.Administrator.ToString(),
+ AppPermissions.AppSettingsWrite)
};
- private void AddDefaultPermissions()
+ foreach ( var rolePermissionsDictionary in existingRolePermissions )
{
- foreach ( var permissionEnum in AllPermissions )
- {
- var permission = _dbContext.Permissions.FirstOrDefault(p => p.Code == permissionEnum.ToString());
+ var role = _dbContext.Roles.TagWith("AddDefaultRolePermissions")
+ .FirstOrDefault(p => p.Code == rolePermissionsDictionary.Key);
+ var permission = _dbContext.Permissions.FirstOrDefault(p =>
+ p.Code == rolePermissionsDictionary.Value.ToString());
- if ( permission != null ) continue;
+ if ( permission == null || role == null ) continue;
+ var rolePermission = _dbContext.RolePermissions.FirstOrDefault(p =>
+ p.RoleId == role.Id && p.PermissionId == permission.Id);
- permission = new Permission()
- {
- Name = permissionEnum.ToString(),
- Code = permissionEnum.ToString(),
- Position = ( int )permissionEnum,
- };
- _dbContext.Permissions.Add(permission);
- _dbContext.SaveChanges();
- }
- }
+ if ( rolePermission != null ) continue;
- private void AddDefaultRolePermissions()
- {
- var existingRolePermissions = new List>
- {
- new KeyValuePair(
- AccountRoles.AppAccountRoles.Administrator.ToString(), AppPermissions.AppSettingsWrite),
- };
+ rolePermission = new RolePermission { RoleId = role.Id, PermissionId = permission.Id };
- foreach ( var rolePermissionsDictionary in existingRolePermissions )
- {
- var role = _dbContext.Roles.TagWith("AddDefaultRolePermissions").FirstOrDefault(p => p.Code == rolePermissionsDictionary.Key);
- var permission = _dbContext.Permissions.FirstOrDefault(p =>
- p.Code == rolePermissionsDictionary.Value.ToString());
-
- if ( permission == null || role == null ) continue;
- var rolePermission = _dbContext.RolePermissions.FirstOrDefault(p =>
- p.RoleId == role.Id && p.PermissionId == permission.Id);
-
- if ( rolePermission != null )
- {
- continue;
- }
-
- rolePermission = new RolePermission
- {
- RoleId = role.Id,
- PermissionId = permission.Id
- };
-
- _dbContext.RolePermissions.Add(rolePermission);
- _dbContext.SaveChanges();
- }
+ _dbContext.RolePermissions.Add(rolePermission);
+ _dbContext.SaveChanges();
}
}
}
diff --git a/starsky/starsky.foundation.database/Migrations/20240901203338_iteration100K.Designer.cs b/starsky/starsky.foundation.database/Migrations/20240901203338_iteration100K.Designer.cs
new file mode 100644
index 0000000000..fb18428649
--- /dev/null
+++ b/starsky/starsky.foundation.database/Migrations/20240901203338_iteration100K.Designer.cs
@@ -0,0 +1,543 @@
+//
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using starsky.foundation.database.Data;
+
+#nullable disable
+
+namespace starsky.foundation.database.Migrations
+{
+ [DbContext(typeof(ApplicationDbContext))]
+ [Migration("20240901203338_iteration100K")]
+ partial class iteration100K
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("MySql:CharSet", "utf8mb4")
+ .HasAnnotation("MySql:CharSetDelegation", DelegationModes.ApplyToAll)
+ .HasAnnotation("ProductVersion", "8.0.8");
+
+ modelBuilder.Entity("starsky.foundation.database.Models.Account.Credential", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER")
+ .HasAnnotation("MySql:ValueGeneratedOnAdd", true);
+
+ b.Property("CredentialTypeId")
+ .HasColumnType("INTEGER");
+
+ b.Property("Extra")
+ .HasColumnType("TEXT");
+
+ b.Property("Identifier")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("TEXT");
+
+ b.Property("IterationCount")
+ .HasColumnType("INTEGER");
+
+ b.Property("Secret")
+ .HasMaxLength(1024)
+ .HasColumnType("TEXT");
+
+ b.Property("UserId")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Id");
+
+ b.HasIndex("CredentialTypeId");
+
+ b.HasIndex("UserId");
+
+ b.HasIndex("Id", "Identifier");
+
+ b.ToTable("Credentials", (string)null);
+
+ b.HasAnnotation("MySql:CharSet", "utf8mb4");
+ });
+
+ modelBuilder.Entity("starsky.foundation.database.Models.Account.CredentialType", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER")
+ .HasAnnotation("MySql:ValueGeneratedOnAdd", true);
+
+ b.Property("Code")
+ .IsRequired()
+ .HasMaxLength(32)
+ .HasColumnType("TEXT");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("TEXT");
+
+ b.Property("Position")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Id");
+
+ b.ToTable("CredentialTypes", (string)null);
+
+ b.HasAnnotation("MySql:CharSet", "utf8mb4");
+ });
+
+ modelBuilder.Entity("starsky.foundation.database.Models.Account.Permission", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER")
+ .HasAnnotation("MySql:ValueGeneratedOnAdd", true);
+
+ b.Property("Code")
+ .IsRequired()
+ .HasMaxLength(32)
+ .HasColumnType("TEXT");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("TEXT");
+
+ b.Property("Position")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Id");
+
+ b.ToTable("Permissions", (string)null);
+
+ b.HasAnnotation("MySql:CharSet", "utf8mb4");
+ });
+
+ modelBuilder.Entity("starsky.foundation.database.Models.Account.Role", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER")
+ .HasAnnotation("MySql:ValueGeneratedOnAdd", true);
+
+ b.Property("Code")
+ .IsRequired()
+ .HasMaxLength(32)
+ .HasColumnType("TEXT");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("TEXT");
+
+ b.Property("Position")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Id");
+
+ b.ToTable("Roles", (string)null);
+
+ b.HasAnnotation("MySql:CharSet", "utf8mb4");
+ });
+
+ modelBuilder.Entity("starsky.foundation.database.Models.Account.RolePermission", b =>
+ {
+ b.Property("RoleId")
+ .HasColumnType("INTEGER");
+
+ b.Property("PermissionId")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("RoleId", "PermissionId");
+
+ b.HasIndex("PermissionId");
+
+ b.ToTable("RolePermissions", (string)null);
+
+ b.HasAnnotation("MySql:CharSet", "utf8mb4");
+ });
+
+ modelBuilder.Entity("starsky.foundation.database.Models.Account.User", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER")
+ .HasAnnotation("MySql:ValueGeneratedOnAdd", true);
+
+ b.Property("AccessFailedCount")
+ .HasColumnType("INTEGER");
+
+ b.Property("Created")
+ .HasColumnType("TEXT");
+
+ b.Property("LockoutEnabled")
+ .HasColumnType("INTEGER");
+
+ b.Property("LockoutEnd")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id");
+
+ b.ToTable("Users", (string)null);
+
+ b.HasAnnotation("MySql:CharSet", "utf8mb4");
+ });
+
+ modelBuilder.Entity("starsky.foundation.database.Models.Account.UserRole", b =>
+ {
+ b.Property("UserId")
+ .HasColumnType("INTEGER");
+
+ b.Property("RoleId")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("UserId", "RoleId");
+
+ b.HasIndex("RoleId");
+
+ b.ToTable("UserRoles", (string)null);
+
+ b.HasAnnotation("MySql:CharSet", "utf8mb4");
+ });
+
+ modelBuilder.Entity("starsky.foundation.database.Models.DataProtectionKey", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER")
+ .HasAnnotation("MySql:ValueGeneratedOnAdd", true);
+
+ b.Property("FriendlyName")
+ .HasMaxLength(45)
+ .HasColumnType("TEXT");
+
+ b.Property("Xml")
+ .HasMaxLength(1200)
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id");
+
+ b.ToTable("DataProtectionKeys");
+
+ b.HasAnnotation("MySql:CharSet", "utf8mb4");
+ });
+
+ modelBuilder.Entity("starsky.foundation.database.Models.FileIndexItem", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("AddToDatabase")
+ .HasColumnType("TEXT");
+
+ b.Property("Aperture")
+ .HasColumnType("REAL");
+
+ b.Property("ColorClass")
+ .HasColumnType("INTEGER");
+
+ b.Property("DateTime")
+ .HasColumnType("TEXT");
+
+ b.Property("Description")
+ .HasColumnType("TEXT");
+
+ b.Property("FileHash")
+ .HasMaxLength(190)
+ .HasColumnType("TEXT");
+
+ b.Property("FileName")
+ .HasMaxLength(190)
+ .HasColumnType("TEXT")
+ .HasColumnOrder(1);
+
+ b.Property("FilePath")
+ .HasMaxLength(380)
+ .HasColumnType("TEXT")
+ .HasColumnOrder(2);
+
+ b.Property("FocalLength")
+ .HasColumnType("REAL");
+
+ b.Property("ImageFormat")
+ .HasColumnType("INTEGER");
+
+ b.Property("ImageHeight")
+ .HasColumnType("INTEGER");
+
+ b.Property("ImageStabilisation")
+ .HasColumnType("INTEGER");
+
+ b.Property("ImageWidth")
+ .HasColumnType("INTEGER");
+
+ b.Property("IsDirectory")
+ .HasColumnType("INTEGER");
+
+ b.Property("IsoSpeed")
+ .HasColumnType("INTEGER");
+
+ b.Property("LastEdited")
+ .HasColumnType("TEXT");
+
+ b.Property("Latitude")
+ .HasColumnType("REAL");
+
+ b.Property("LocationAltitude")
+ .HasColumnType("REAL");
+
+ b.Property("LocationCity")
+ .HasMaxLength(40)
+ .HasColumnType("TEXT");
+
+ b.Property("LocationCountry")
+ .HasMaxLength(40)
+ .HasColumnType("TEXT");
+
+ b.Property("LocationCountryCode")
+ .HasMaxLength(3)
+ .HasColumnType("TEXT");
+
+ b.Property("LocationState")
+ .HasMaxLength(40)
+ .HasColumnType("TEXT");
+
+ b.Property("Longitude")
+ .HasColumnType("REAL");
+
+ b.Property("MakeModel")
+ .HasColumnType("TEXT");
+
+ b.Property("Orientation")
+ .HasColumnType("INTEGER");
+
+ b.Property("ParentDirectory")
+ .HasMaxLength(190)
+ .HasColumnType("TEXT");
+
+ b.Property("ShutterSpeed")
+ .HasMaxLength(20)
+ .HasColumnType("TEXT");
+
+ b.Property("SidecarExtensions")
+ .HasColumnType("TEXT");
+
+ b.Property("Size")
+ .HasColumnType("bigint");
+
+ b.Property("Software")
+ .HasMaxLength(40)
+ .HasColumnType("TEXT");
+
+ b.Property("Tags")
+ .HasMaxLength(1024)
+ .HasColumnType("TEXT");
+
+ b.Property("Title")
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id");
+
+ b.HasIndex("FileName", "ParentDirectory");
+
+ b.ToTable("FileIndex");
+
+ b.HasAnnotation("MySql:CharSet", "utf8mb4");
+ });
+
+ modelBuilder.Entity("starsky.foundation.database.Models.ImportIndexItem", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("AddToDatabase")
+ .HasColumnType("TEXT");
+
+ b.Property("ColorClass")
+ .HasColumnType("INTEGER");
+
+ b.Property("DateTime")
+ .HasColumnType("TEXT");
+
+ b.Property("DateTimeFromFileName")
+ .HasColumnType("INTEGER");
+
+ b.Property("FileHash")
+ .HasColumnType("TEXT");
+
+ b.Property("FilePath")
+ .HasColumnType("TEXT");
+
+ b.Property("MakeModel")
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id");
+
+ b.HasIndex("FileHash")
+ .HasAnnotation("MySql:CharSet", "utf8mb4");
+
+ b.ToTable("ImportIndex");
+ });
+
+ modelBuilder.Entity("starsky.foundation.database.Models.NotificationItem", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER")
+ .HasAnnotation("MySql:ValueGeneratedOnAdd", true)
+ .HasAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn)
+ .HasAnnotation("Sqlite:Autoincrement", true);
+
+ b.Property("Content")
+ .HasColumnType("mediumtext");
+
+ b.Property("DateTime")
+ .IsConcurrencyToken()
+ .HasColumnType("TEXT");
+
+ b.Property("DateTimeEpoch")
+ .HasColumnType("bigint");
+
+ b.HasKey("Id");
+
+ b.ToTable("Notifications", (string)null);
+
+ b.HasAnnotation("MySql:CharSet", "utf8mb4");
+ });
+
+ modelBuilder.Entity("starsky.foundation.database.Models.SettingsItem", b =>
+ {
+ b.Property("Key")
+ .HasMaxLength(150)
+ .HasColumnType("varchar(150)");
+
+ b.Property("IsUserEditable")
+ .HasColumnType("INTEGER");
+
+ b.Property("UserId")
+ .HasColumnType("INTEGER");
+
+ b.Property("Value")
+ .IsRequired()
+ .HasMaxLength(4096)
+ .HasColumnType("TEXT");
+
+ b.HasKey("Key");
+
+ b.ToTable("Settings", (string)null);
+
+ b.HasAnnotation("MySql:CharSet", "utf8mb4");
+ });
+
+ modelBuilder.Entity("starsky.foundation.database.Models.ThumbnailItem", b =>
+ {
+ b.Property("FileHash")
+ .HasMaxLength(190)
+ .HasColumnType("varchar(190)");
+
+ b.Property("ExtraLarge")
+ .HasColumnType("INTEGER");
+
+ b.Property("Large")
+ .HasColumnType("INTEGER");
+
+ b.Property("Reasons")
+ .HasColumnType("TEXT");
+
+ b.Property("Small")
+ .HasColumnType("INTEGER");
+
+ b.Property("TinyMeta")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("FileHash");
+
+ b.ToTable("Thumbnails", (string)null);
+
+ b.HasAnnotation("MySql:CharSet", "utf8mb4");
+ });
+
+ modelBuilder.Entity("starsky.foundation.database.Models.Account.Credential", b =>
+ {
+ b.HasOne("starsky.foundation.database.Models.Account.CredentialType", "CredentialType")
+ .WithMany("Credentials")
+ .HasForeignKey("CredentialTypeId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("starsky.foundation.database.Models.Account.User", "User")
+ .WithMany("Credentials")
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("CredentialType");
+
+ b.Navigation("User");
+ });
+
+ modelBuilder.Entity("starsky.foundation.database.Models.Account.RolePermission", b =>
+ {
+ b.HasOne("starsky.foundation.database.Models.Account.Permission", "Permission")
+ .WithMany()
+ .HasForeignKey("PermissionId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("starsky.foundation.database.Models.Account.Role", "Role")
+ .WithMany()
+ .HasForeignKey("RoleId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Permission");
+
+ b.Navigation("Role");
+ });
+
+ modelBuilder.Entity("starsky.foundation.database.Models.Account.UserRole", b =>
+ {
+ b.HasOne("starsky.foundation.database.Models.Account.Role", "Role")
+ .WithMany()
+ .HasForeignKey("RoleId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("starsky.foundation.database.Models.Account.User", "User")
+ .WithMany()
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Role");
+
+ b.Navigation("User");
+ });
+
+ modelBuilder.Entity("starsky.foundation.database.Models.Account.CredentialType", b =>
+ {
+ b.Navigation("Credentials");
+ });
+
+ modelBuilder.Entity("starsky.foundation.database.Models.Account.User", b =>
+ {
+ b.Navigation("Credentials");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/starsky/starsky.foundation.database/Migrations/20240901203338_iteration100K.cs b/starsky/starsky.foundation.database/Migrations/20240901203338_iteration100K.cs
new file mode 100644
index 0000000000..8d19d526ce
--- /dev/null
+++ b/starsky/starsky.foundation.database/Migrations/20240901203338_iteration100K.cs
@@ -0,0 +1,29 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace starsky.foundation.database.Migrations
+{
+ ///
+ public partial class iteration100K : Migration
+ {
+ ///
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.AddColumn(
+ name: "IterationCount",
+ table: "Credentials",
+ type: "INTEGER",
+ nullable: false,
+ defaultValue: 0);
+ }
+
+ ///
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropColumn(
+ name: "IterationCount",
+ table: "Credentials");
+ }
+ }
+}
diff --git a/starsky/starsky.foundation.database/Migrations/ApplicationDbContextModelSnapshot.cs b/starsky/starsky.foundation.database/Migrations/ApplicationDbContextModelSnapshot.cs
index 594056de5f..403b443bf3 100644
--- a/starsky/starsky.foundation.database/Migrations/ApplicationDbContextModelSnapshot.cs
+++ b/starsky/starsky.foundation.database/Migrations/ApplicationDbContextModelSnapshot.cs
@@ -19,7 +19,7 @@ protected override void BuildModel(ModelBuilder modelBuilder)
modelBuilder
.HasAnnotation("MySql:CharSet", "utf8mb4")
.HasAnnotation("MySql:CharSetDelegation", DelegationModes.ApplyToAll)
- .HasAnnotation("ProductVersion", "8.0.1");
+ .HasAnnotation("ProductVersion", "8.0.8");
modelBuilder.Entity("starsky.foundation.database.Models.Account.Credential", b =>
{
@@ -39,6 +39,9 @@ protected override void BuildModel(ModelBuilder modelBuilder)
.HasMaxLength(64)
.HasColumnType("TEXT");
+ b.Property("IterationCount")
+ .HasColumnType("INTEGER");
+
b.Property("Secret")
.HasMaxLength(1024)
.HasColumnType("TEXT");
diff --git a/starsky/starsky.foundation.database/Models/Account/Credential.cs b/starsky/starsky.foundation.database/Models/Account/Credential.cs
index 49091bdccf..99eb05dbc0 100755
--- a/starsky/starsky.foundation.database/Models/Account/Credential.cs
+++ b/starsky/starsky.foundation.database/Models/Account/Credential.cs
@@ -32,5 +32,6 @@ public class Credential
public string? Extra { get; set; }
public User? User { get; set; }
public CredentialType? CredentialType { get; set; }
+ public IterationCountType IterationCount { get; set; }
}
}
diff --git a/starsky/starsky.foundation.database/Models/Account/IterationCountType.cs b/starsky/starsky.foundation.database/Models/Account/IterationCountType.cs
new file mode 100644
index 0000000000..ecb98545dd
--- /dev/null
+++ b/starsky/starsky.foundation.database/Models/Account/IterationCountType.cs
@@ -0,0 +1,8 @@
+namespace starsky.foundation.database.Models.Account;
+
+public enum IterationCountType
+{
+ Default = 0,
+ IterateLegacySha1 = 10_000,
+ Iterate100KSha256 = 100_000,
+}
diff --git a/starsky/starsky.foundation.platform/Models/AppSettingsPublishProfiles.cs b/starsky/starsky.foundation.platform/Models/AppSettingsPublishProfiles.cs
index edb32628e6..9cd470f111 100644
--- a/starsky/starsky.foundation.platform/Models/AppSettingsPublishProfiles.cs
+++ b/starsky/starsky.foundation.platform/Models/AppSettingsPublishProfiles.cs
@@ -118,11 +118,9 @@ public void ResetPath()
///
public string Path
{
- get
- {
+ get =>
// return: if null > string.Empty
- return string.IsNullOrEmpty(PathPrivate) ? string.Empty : PathPrivate;
- }
+ string.IsNullOrEmpty(PathPrivate) ? string.Empty : PathPrivate;
set
{
if ( string.IsNullOrEmpty(value) )
@@ -151,7 +149,7 @@ public string Path
///
public string Folder
{
- get { return _folder; }
+ get => _folder;
set
{
// Append slash after
diff --git a/starsky/starskytest/FakeMocks/FakeIUserManger.cs b/starsky/starskytest/FakeMocks/FakeIUserManger.cs
index 771cb53227..9f08d56ab5 100644
--- a/starsky/starskytest/FakeMocks/FakeIUserManger.cs
+++ b/starsky/starskytest/FakeMocks/FakeIUserManger.cs
@@ -1,3 +1,5 @@
+using System;
+using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
@@ -21,46 +23,72 @@ public Task AllUsersAsync()
return Task.FromResult(_userOverviewModel);
}
- public Task SignUpAsync(string name, string credentialTypeCode, string? identifier,
+ public Task SignUpAsync(string name, string credentialTypeCode,
+ string? identifier,
string? secret)
{
- throw new System.NotImplementedException();
+ _userOverviewModel.Users.Add(new User
+ {
+ Name = name,
+ Credentials = new List
+ {
+ new()
+ {
+ CredentialType = new CredentialType { Code = "email" },
+ Identifier = identifier,
+ Secret = secret,
+ IterationCount = IterationCountType.Iterate100KSha256
+ }
+ }
+ });
+
+ return Task.FromResult(new SignUpResult());
}
public void AddToRole(User user, string roleCode)
{
- throw new System.NotImplementedException();
+ throw new NotImplementedException();
}
public void AddToRole(User user, Role role)
{
- throw new System.NotImplementedException();
+ throw new NotImplementedException();
}
public void RemoveFromRole(User user, string roleCode)
{
- throw new System.NotImplementedException();
+ throw new NotImplementedException();
}
public void RemoveFromRole(User user, Role role)
{
- throw new System.NotImplementedException();
+ throw new NotImplementedException();
}
public ChangeSecretResult ChangeSecret(string credentialTypeCode, string? identifier,
string secret)
{
- throw new System.NotImplementedException();
+ var result = _userOverviewModel.Users.Find(p =>
+ p.Credentials?.FirstOrDefault()?.Identifier == identifier);
+ if ( result == null )
+ return new ChangeSecretResult(false, ChangeSecretResultError.CredentialNotFound);
+ result.Credentials!.FirstOrDefault()!.IterationCount = IterationCountType.Iterate100KSha256;
+ result.Credentials!.FirstOrDefault()!.Secret = secret;
+
+ return new ChangeSecretResult(true);
}
- public Task ValidateAsync(string credentialTypeCode, string? identifier, string secret)
+ public Task ValidateAsync(string credentialTypeCode, string? identifier,
+ string secret)
{
var validateResult = new ValidateResult();
- var result = _userOverviewModel.Users.Find(p => p.Credentials?.FirstOrDefault()?.Identifier == identifier);
+ var result = _userOverviewModel.Users.Find(p =>
+ p.Credentials?.FirstOrDefault()?.Identifier == identifier);
+
if ( result?.Credentials?.FirstOrDefault()?.Secret == secret )
- {
validateResult.Success = true;
- }
+ else
+ validateResult.Error = ValidateResultError.SecretNotValid;
return Task.FromResult(validateResult);
}
@@ -72,57 +100,65 @@ public Task SignIn(HttpContext httpContext, User? user, bool isPersistent
public void SignOut(HttpContext httpContext)
{
- throw new System.NotImplementedException();
+ throw new NotImplementedException();
}
public int GetCurrentUserId(HttpContext httpContext)
{
- throw new System.NotImplementedException();
+ throw new NotImplementedException();
}
public User GetCurrentUser(HttpContext httpContext)
{
- throw new System.NotImplementedException();
+ throw new NotImplementedException();
}
- public User GetUser(string credentialTypeCode, string identifier)
+ public User? GetUser(string credentialTypeCode, string identifier)
{
- throw new System.NotImplementedException();
+ return _userOverviewModel.Users.Find(p => p.Credentials?.Any(credential =>
+ credential.Identifier == identifier) == true);
}
- public Credential GetCredentialsByUserId(int userId)
+ public Credential? GetCredentialsByUserId(int userId)
{
- throw new System.NotImplementedException();
+ return _userOverviewModel.Users.Find(p => p.Credentials?.Any(credential =>
+ credential.Id == 0) == true)?.Credentials?.FirstOrDefault(p =>
+ p.Id == 0);
}
public Task RemoveUser(string credentialTypeCode, string identifier)
{
- throw new System.NotImplementedException();
+ throw new NotImplementedException();
}
public User Exist(string identifier)
{
- throw new System.NotImplementedException();
+ throw new NotImplementedException();
}
public Task ExistAsync(int userTableId)
{
- throw new System.NotImplementedException();
+ throw new NotImplementedException();
}
public Role GetRole(string credentialTypeCode, string identifier)
{
- throw new System.NotImplementedException();
+ throw new NotImplementedException();
}
public Task GetRoleAsync(int userId)
{
- throw new System.NotImplementedException();
+ throw new NotImplementedException();
}
public bool PreflightValidate(string userName, string password,
string confirmPassword)
{
- throw new System.NotImplementedException();
+ throw new NotImplementedException();
+ }
+
+ public CredentialType? GetCachedCredentialType(string email)
+ {
+ return new CredentialType { Code = "email" };
}
}
diff --git a/starsky/starskytest/FakeMocks/FakeUserManagerActiveUsers.cs b/starsky/starskytest/FakeMocks/FakeUserManagerActiveUsers.cs
index 19cb1d6b18..3ef833c73c 100644
--- a/starsky/starskytest/FakeMocks/FakeUserManagerActiveUsers.cs
+++ b/starsky/starskytest/FakeMocks/FakeUserManagerActiveUsers.cs
@@ -1,4 +1,6 @@
+using System;
using System.Collections.Generic;
+using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using starsky.foundation.accountmanagement.Interfaces;
@@ -6,162 +8,176 @@
using starsky.foundation.database.Models.Account;
using starsky.foundation.platform.Models;
-namespace starskytest.FakeMocks
+namespace starskytest.FakeMocks;
+
+public class FakeUserManagerActiveUsers : IUserManager
{
- public class FakeUserManagerActiveUsers : IUserManager
+ public FakeUserManagerActiveUsers(string identifier = "test", User? currentUser = null)
{
+ CurrentUser = currentUser;
+ Credentials = new Credential
+ {
+ UserId = 1,
+ Identifier = identifier,
+ Secret = "NNzKymrSy9IkybnFxwVvTRiAYuiOUoPHvXwBJybORrQ=", // test123456789
+ Extra = "TgBCDRHGklOMqJ/mAJYqHg==",
+ CredentialTypeId = 1
+ };
+ Role = new Role { Code = AccountRoles.AppAccountRoles.User.ToString() };
+ }
- public FakeUserManagerActiveUsers(string identifier = "test", User? currentUser = null )
- {
- CurrentUser = currentUser;
- Credentials = new Credential
- {
- UserId = 1,
- Identifier = identifier,
- Secret = "NNzKymrSy9IkybnFxwVvTRiAYuiOUoPHvXwBJybORrQ=", // test123456789
- Extra = "TgBCDRHGklOMqJ/mAJYqHg==",
- CredentialTypeId = 1
- };
- Role = new Role {Code = AccountRoles.AppAccountRoles.User.ToString()};
- }
-
- public User? CurrentUser { get; set; }
- public Credential Credentials { get; set; }
- public Role? Role { get; set; }
-
- public List Users { get; set; } = new List();
-
- public Task AllUsersAsync()
- {
- // null can be for testing
- return Task.FromResult(new UserOverviewModel(new List{CurrentUser!}));
- }
+ public User? CurrentUser { get; set; }
+ public Credential Credentials { get; set; }
+ public Role? Role { get; set; }
- public void AddUserToCache(User user)
- {
- throw new System.NotImplementedException();
- }
+ public List Users { get; set; } = new();
- public Task SignUpAsync(string name, string credentialTypeCode,
- string? identifier, string? secret)
+ public Task AllUsersAsync()
+ {
+ // null can be for testing
+ return Task.FromResult(new UserOverviewModel(new List { CurrentUser! }));
+ }
+
+ public Task SignUpAsync(string name, string credentialTypeCode,
+ string? identifier, string? secret)
+ {
+ Users.Add(new User
{
- Users.Add(new User{Name = name, Credentials = new List
+ Name = name,
+ Credentials = new List
{
- new Credential{ CredentialType = new CredentialType{Code = "email"}, Identifier = identifier, Secret = secret}
- }});
-
- return Task.FromResult(new SignUpResult());
- }
+ new()
+ {
+ CredentialType = new CredentialType { Code = "email" },
+ Identifier = identifier,
+ Secret = secret,
+ IterationCount = IterationCountType.Iterate100KSha256
+ }
+ }
+ });
- public void AddToRole(User user, string roleCode)
- {
- AddToRole(user,new Role{Code = roleCode});
- }
+ return Task.FromResult(new SignUpResult());
+ }
- public void AddToRole(User user, Role role)
- {
- Role = role;
- }
+ public void AddToRole(User user, string roleCode)
+ {
+ AddToRole(user, new Role { Code = roleCode });
+ }
- public void RemoveFromRole(User user, string roleCode)
- {
- Role = null;
- }
+ public void AddToRole(User user, Role role)
+ {
+ Role = role;
+ }
- public void RemoveFromRole(User user, Role role)
- {
- Role = null;
- }
+ public void RemoveFromRole(User user, string roleCode)
+ {
+ Role = null;
+ }
- public ChangeSecretResult ChangeSecret(string credentialTypeCode, string? identifier, string secret)
- {
- return new ChangeSecretResult{Success = true};
- }
+ public void RemoveFromRole(User user, Role role)
+ {
+ Role = null;
+ }
+
+ public ChangeSecretResult ChangeSecret(string credentialTypeCode, string? identifier,
+ string secret)
+ {
+ return new ChangeSecretResult { Success = true };
+ }
#pragma warning disable 1998
- public async Task ValidateAsync(string credentialTypeCode, string? identifier, string secret)
+ public async Task ValidateAsync(string credentialTypeCode, string? identifier,
+ string secret)
#pragma warning restore 1998
+ {
+ return identifier switch
{
- return identifier switch
+ // this user is rejected
+ "reject" => new ValidateResult
{
- // this user is rejected
- "reject" => new ValidateResult
- {
- Success = false,
- Error = ValidateResultError.CredentialNotFound
- },
- "lockout" => new ValidateResult
- {
- Success = false,
- Error = ValidateResultError.Lockout
- },
- _ => new ValidateResult { Success = true }
- };
- }
-
- public Task SignIn(HttpContext httpContext, User? user, bool isPersistent = false)
- {
- return Task.FromResult(true);
- }
+ Success = false, Error = ValidateResultError.CredentialNotFound
+ },
+ "lockout" => new ValidateResult
+ {
+ Success = false, Error = ValidateResultError.Lockout
+ },
+ _ => new ValidateResult { Success = true }
+ };
+ }
- public void SignOut(HttpContext httpContext)
- {
- throw new System.NotImplementedException();
- }
+ public Task SignIn(HttpContext httpContext, User? user, bool isPersistent = false)
+ {
+ return Task.FromResult(true);
+ }
- public int GetCurrentUserId(HttpContext httpContext)
- {
- throw new System.NotImplementedException();
- }
+ public void SignOut(HttpContext httpContext)
+ {
+ throw new NotImplementedException();
+ }
- public User? GetCurrentUser(HttpContext httpContext)
- {
- return CurrentUser;
- }
+ public int GetCurrentUserId(HttpContext httpContext)
+ {
+ throw new NotImplementedException();
+ }
- public User? GetUser(string credentialTypeCode, string identifier)
- {
- return CurrentUser;
- }
+ public User? GetCurrentUser(HttpContext httpContext)
+ {
+ return CurrentUser;
+ }
- public Credential GetCredentialsByUserId(int userId)
- {
- return Credentials;
- }
+ public User? GetUser(string credentialTypeCode, string identifier)
+ {
+ if ( CurrentUser != null && !Users.Contains(CurrentUser!) )
+ Users.Add(CurrentUser!);
- public Task RemoveUser(string credentialTypeCode,
- string identifier)
- {
- return Task.FromResult(new ValidateResult());
- }
+ return Users.Find(p => p.Credentials?.Any(credential =>
+ credential.Identifier == identifier) == true);
+ }
- public User? Exist(string identifier)
- {
- if ( Credentials.Identifier == identifier )
- {
- return CurrentUser;
- }
- return null;
- }
+ public Credential GetCredentialsByUserId(int userId)
+ {
+ return Credentials;
+ }
- public Task ExistAsync(int userTableId)
- {
- return Task.FromResult(CurrentUser);
- }
+ public Task RemoveUser(string credentialTypeCode,
+ string identifier)
+ {
+ return Task.FromResult(new ValidateResult());
+ }
- public Role? GetRole(string credentialTypeCode, string identifier)
- {
- return Role;
- }
+ public User? Exist(string identifier)
+ {
+ if ( Credentials.Identifier == identifier ) return CurrentUser;
+ return null;
+ }
- public Task GetRoleAsync(int userId)
- {
- return Task.FromResult(Role);
- }
+ public Task ExistAsync(int userTableId)
+ {
+ return Task.FromResult(CurrentUser);
+ }
- public bool PreflightValidate(string userName, string password, string confirmPassword)
- {
- return password != "false";
- }
+ public Role? GetRole(string credentialTypeCode, string identifier)
+ {
+ return Role;
+ }
+
+ public Task GetRoleAsync(int userId)
+ {
+ return Task.FromResult(Role);
+ }
+
+ public bool PreflightValidate(string userName, string password, string confirmPassword)
+ {
+ return password != "false";
+ }
+
+ public CredentialType? GetCachedCredentialType(string email)
+ {
+ return new CredentialType { Code = "email" };
+ }
+
+ public void AddUserToCache(User user)
+ {
+ throw new NotImplementedException();
}
}
diff --git a/starsky/starskytest/starsky.foundation.accountmanagement/Helpers/Pbkdf2HasherTests.cs b/starsky/starskytest/starsky.foundation.accountmanagement/Helpers/Pbkdf2HasherTests.cs
new file mode 100644
index 0000000000..141ad2721c
--- /dev/null
+++ b/starsky/starskytest/starsky.foundation.accountmanagement/Helpers/Pbkdf2HasherTests.cs
@@ -0,0 +1,150 @@
+using System;
+using System.Security.Cryptography;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using starsky.foundation.accountmanagement.Helpers;
+
+namespace starskytest.starsky.foundation.accountmanagement.Helpers;
+
+[TestClass]
+public class Pbkdf2HasherTests
+{
+ [TestMethod]
+ public void ComputeHash_ReturnsHash_ForValidInputs()
+ {
+ // Arrange
+ const string password = "testPassword";
+ var salt = new byte[16];
+ RandomNumberGenerator.Fill(salt);
+
+ // Act
+ var hash = Pbkdf2Hasher.ComputeHash(password, salt);
+
+ // Assert
+ Assert.IsNotNull(hash);
+ Assert.IsTrue(hash.Length > 0);
+ }
+
+ [TestMethod]
+ public void ComputeHash_ConsistentResults_ForSameInputs()
+ {
+ // Arrange
+ const string password = "consistentPassword";
+ var salt = new byte[16];
+ RandomNumberGenerator.Fill(salt);
+
+ // Act
+ var hash1 = Pbkdf2Hasher.ComputeHash(password, salt);
+ var hash2 = Pbkdf2Hasher.ComputeHash(password, salt);
+
+ // Assert
+ Assert.AreEqual(hash1, hash2);
+ }
+
+ [TestMethod]
+ public void ComputeHash_DifferentResults_ForDifferentSalts()
+ {
+ // Arrange
+ const string password = "testPassword";
+ var salt1 = new byte[16];
+ var salt2 = new byte[16];
+ RandomNumberGenerator.Fill(salt1);
+ RandomNumberGenerator.Fill(salt2);
+
+ // Act
+ var hash1 = Pbkdf2Hasher.ComputeHash(password, salt1);
+ var hash2 = Pbkdf2Hasher.ComputeHash(password, salt2);
+
+ // Assert
+ Assert.AreNotEqual(hash1, hash2);
+ }
+
+ [TestMethod]
+ public void ComputeHash_DifferentIterationCounts_ReturnsDifferentHashes()
+ {
+ // Arrange
+ const string password = "testPassword";
+ var salt = new byte[16];
+ RandomNumberGenerator.Fill(salt);
+
+ // Act
+ var hash1 = Pbkdf2Hasher.ComputeHash(password, salt, false); // 10,000 iterations
+ var hash2 = Pbkdf2Hasher.ComputeHash(password, salt); // 100,000 iterations
+
+ // Assert
+ Assert.AreNotEqual(hash1, hash2);
+ }
+
+ [TestMethod]
+ public void ComputeHash_DifferentIterations_HashesCompareLengths()
+ {
+ // Arrange
+ const string password = "testPassword";
+ var salt = new byte[16];
+ RandomNumberGenerator.Fill(salt);
+
+ // Act
+ var hash1 = Pbkdf2Hasher.ComputeHash(password, salt,false); // 10,000 iterations
+ var hash2 = Pbkdf2Hasher.ComputeHash(password, salt); // 100,000 iterations
+
+ // Assert
+ Assert.AreEqual(hash1.Length, hash2.Length, "Hashes should have the same length regardless of iterations.");
+ Assert.AreNotEqual(hash1, hash2, "Hashes should differ due to different iteration counts.");
+ }
+
+ [TestMethod]
+ public void ComputeHash_ThrowsArgumentNullException_ForNullSalt()
+ {
+ // Arrange
+ const string password = "testPassword";
+
+ // Act and Assert
+ Assert.ThrowsException(() => Pbkdf2Hasher.ComputeHash(password, null!));
+ }
+
+ [TestMethod]
+ public void ComputeHash_ThrowsArgumentNullException_ForNullPassword()
+ {
+ // Arrange
+ var salt = new byte[16];
+ RandomNumberGenerator.Fill(salt);
+
+ // Act and Assert
+ Assert.ThrowsException(() => Pbkdf2Hasher.ComputeHash(null!, salt));
+ }
+
+ [TestMethod]
+ public void ComputeHash_ReturnsDifferentHashes_ForDifferentPasswords()
+ {
+ // Arrange
+ var salt = new byte[16];
+ RandomNumberGenerator.Fill(salt);
+
+ // Act
+ var hash1 = Pbkdf2Hasher.ComputeHash("password1", salt);
+ var hash2 = Pbkdf2Hasher.ComputeHash("password2", salt);
+
+ // Assert
+ Assert.AreNotEqual(hash1, hash2);
+ }
+
+ [TestMethod]
+ public void GenerateRandomSalt_ShouldReturnCorrectLength()
+ {
+ // Act
+ var salt = Pbkdf2Hasher.GenerateRandomSalt();
+
+ // Assert
+ Assert.AreEqual(16, salt.Length); // 128 / 8 = 16
+ }
+
+ [TestMethod]
+ public void GenerateRandomSalt_ShouldReturnUniqueValues()
+ {
+ // Act
+ var salt1 = Pbkdf2Hasher.GenerateRandomSalt();
+ var salt2 = Pbkdf2Hasher.GenerateRandomSalt();
+
+ // Assert NOT EQ
+ Assert.AreNotEqual(salt1, salt2); // Check that the two salts are different
+ }
+}
diff --git a/starsky/starskytest/starsky.foundation.accountmanagement/Services/UserManagerTest.cs b/starsky/starskytest/starsky.foundation.accountmanagement/Services/UserManagerTest.cs
index 5240c1c803..d8e4085ba2 100644
--- a/starsky/starskytest/starsky.foundation.accountmanagement/Services/UserManagerTest.cs
+++ b/starsky/starskytest/starsky.foundation.accountmanagement/Services/UserManagerTest.cs
@@ -17,992 +17,1084 @@
using starsky.foundation.platform.Models;
using starskytest.FakeMocks;
-namespace starskytest.starsky.foundation.accountmanagement.Services
+namespace starskytest.starsky.foundation.accountmanagement.Services;
+
+[TestClass]
+public sealed class UserManagerTest
{
- [TestClass]
- public sealed class UserManagerTest
+ private readonly IMemoryCache _memoryCache;
+ private readonly ApplicationDbContext _dbContext;
+
+ public UserManagerTest()
{
- private readonly IMemoryCache _memoryCache;
- private readonly ApplicationDbContext _dbContext;
+ var provider = new ServiceCollection()
+ .AddMemoryCache()
+ .BuildServiceProvider();
+ _memoryCache = provider.GetRequiredService();
+
+ var builder = new DbContextOptionsBuilder();
+ builder.UseInMemoryDatabase(nameof(MetaUpdateService));
+ var options = builder.Options;
+ _dbContext = new ApplicationDbContext(options);
+ }
- public UserManagerTest()
- {
- var provider = new ServiceCollection()
- .AddMemoryCache()
- .BuildServiceProvider();
- _memoryCache = provider.GetRequiredService();
-
- var builder = new DbContextOptionsBuilder();
- builder.UseInMemoryDatabase(nameof(MetaUpdateService));
- var options = builder.Options;
- _dbContext = new ApplicationDbContext(options);
- }
+ [TestMethod]
+ public async Task ValidateAsync_CredentialType_NotFound()
+ {
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
- [TestMethod]
- public async Task ValidateAsync_CredentialType_NotFound()
- {
- var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
- _memoryCache);
+ var result = await userManager.ValidateAsync("not-found", "test", "test");
- var result = await userManager.ValidateAsync("not-found", "test", "test");
+ Assert.IsFalse(result.Success);
+ Assert.AreEqual(ValidateResultError.CredentialTypeNotFound, result.Error);
+ }
+
+ [TestMethod]
+ public async Task ValidateAsync_CredentialType_stringEmpty()
+ {
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
- Assert.IsFalse(result.Success);
- Assert.AreEqual(ValidateResultError.CredentialTypeNotFound, result.Error);
- }
+ var result = await userManager.ValidateAsync(string.Empty, "test", string.Empty);
- [TestMethod]
- public async Task SignInNull()
- {
- var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
- _memoryCache);
- Assert.IsFalse(await userManager.SignIn(new DefaultHttpContext(), null!));
- }
+ Assert.IsFalse(result.Success);
+ Assert.AreEqual(ValidateResultError.SecretNotValid, result.Error);
+ }
+ [TestMethod]
+ public async Task SignInNull()
+ {
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
+ Assert.IsFalse(await userManager.SignIn(new DefaultHttpContext(), null!));
+ }
- [TestMethod]
- public async Task SignInNoUserId()
- {
- var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
- _memoryCache);
- Assert.IsFalse(await userManager.SignIn(new DefaultHttpContext(), new User()));
- }
- [TestMethod]
- [ExpectedException(typeof(ArgumentNullException))]
- public async Task SignInSystemArgumentNullException()
- {
- var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
- _memoryCache);
- // not having SignUpAsync registered
- Assert.IsFalse(await userManager.SignIn(new DefaultHttpContext(), new User { Id = 1 }));
- }
+ [TestMethod]
+ public async Task SignInNoUserId()
+ {
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
+ Assert.IsFalse(await userManager.SignIn(new DefaultHttpContext(), new User()));
+ }
- [TestMethod]
- public void GetUserClaims_NoId()
- {
- var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
- _memoryCache);
+ [TestMethod]
+ [ExpectedException(typeof(ArgumentNullException))]
+ public async Task SignInSystemArgumentNullException()
+ {
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
+ // not having SignUpAsync registered
+ Assert.IsFalse(await userManager.SignIn(new DefaultHttpContext(), new User { Id = 1 }));
+ }
- var claims = userManager.GetUserClaims(new User());
- Assert.AreEqual(0, claims.Count());
- }
+ [TestMethod]
+ public void GetUserClaims_NoId()
+ {
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
- [TestMethod]
- public void GetUserClaims_Null()
- {
- var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
- _memoryCache);
+ var claims = userManager.GetUserClaims(new User());
+ Assert.AreEqual(0, claims.Count());
+ }
- var claims = userManager.GetUserClaims(null);
- Assert.AreEqual(0, claims.Count());
- }
+ [TestMethod]
+ public void GetUserClaims_Null()
+ {
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
- [TestMethod]
- public void GetUserClaims_ShouldReturnClaims()
- {
- var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
- _memoryCache);
+ var claims = userManager.GetUserClaims(null);
+ Assert.AreEqual(0, claims.Count());
+ }
- var claims = userManager
- .GetUserClaims(new User { Name = "test", Id = 1 }).ToList();
+ [TestMethod]
+ public void GetUserClaims_ShouldReturnClaims()
+ {
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
- Assert.AreEqual(1, claims.Count(p => p.Type == ClaimTypes.Name));
- Assert.AreEqual(1, claims.Count(p => p.Type == ClaimTypes.NameIdentifier));
- Assert.AreEqual(1, claims.Count(p => p.Type == ClaimTypes.Email));
- }
+ var claims = userManager
+ .GetUserClaims(new User { Name = "test", Id = 1 }).ToList();
- [TestMethod]
- public void GetUserClaims_ShouldReturnEmail()
- {
- var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
- _memoryCache);
-
- var claims = userManager
- .GetUserClaims(new User
- {
- Name = "test",
- Id = 1,
- Credentials =
- new List { new Credential { Identifier = "email" } }
- }).ToList();
-
- Assert.AreEqual("test", claims.Find(p => p.Type == ClaimTypes.Name)?.Value);
- Assert.AreEqual("1", claims.Find(p => p.Type == ClaimTypes.NameIdentifier)?.Value);
- Assert.AreEqual("email", claims.Find(p => p.Type == ClaimTypes.Email)?.Value);
- }
+ Assert.AreEqual(1, claims.Count(p => p.Type == ClaimTypes.Name));
+ Assert.AreEqual(1, claims.Count(p => p.Type == ClaimTypes.NameIdentifier));
+ Assert.AreEqual(1, claims.Count(p => p.Type == ClaimTypes.Email));
+ }
- [TestMethod]
- public void GetUserClaims_ShouldNotFailDueMissingEmail()
- {
- var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
- _memoryCache);
+ [TestMethod]
+ public void GetUserClaims_ShouldReturnEmail()
+ {
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
- var claims = userManager
- .GetUserClaims(new User { Name = "test", Id = 1, Credentials = null }).ToList();
+ var claims = userManager
+ .GetUserClaims(new User
+ {
+ Name = "test",
+ Id = 1,
+ Credentials =
+ new List { new Credential { Identifier = "email" } }
+ }).ToList();
+
+ Assert.AreEqual("test", claims.Find(p => p.Type == ClaimTypes.Name)?.Value);
+ Assert.AreEqual("1", claims.Find(p => p.Type == ClaimTypes.NameIdentifier)?.Value);
+ Assert.AreEqual("email", claims.Find(p => p.Type == ClaimTypes.Email)?.Value);
+ }
- Assert.AreEqual("test", claims.Find(p => p.Type == ClaimTypes.Name)?.Value);
- Assert.AreEqual("1", claims.Find(p => p.Type == ClaimTypes.NameIdentifier)?.Value);
- Assert.AreEqual("", claims.Find(p => p.Type == ClaimTypes.Email)?.Value);
- }
+ [TestMethod]
+ public void GetUserClaims_ShouldNotFailDueMissingEmail()
+ {
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
+
+ var claims = userManager
+ .GetUserClaims(new User { Name = "test", Id = 1, Credentials = null }).ToList();
+ Assert.AreEqual("test", claims.Find(p => p.Type == ClaimTypes.Name)?.Value);
+ Assert.AreEqual("1", claims.Find(p => p.Type == ClaimTypes.NameIdentifier)?.Value);
+ Assert.AreEqual("", claims.Find(p => p.Type == ClaimTypes.Email)?.Value);
+ }
+
+ [TestMethod]
+ public async Task ValidateAsync_Credential_NotFound()
+ {
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
- [TestMethod]
- public async Task ValidateAsync_Credential_NotFound()
+ var test = await _dbContext.CredentialTypes.AnyAsync(p => p.Code == "email");
+ if (!test)
{
- var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
- _memoryCache);
+ _dbContext.CredentialTypes.Add(
+ new CredentialType { Code = "email", Name = "t" });
+ await _dbContext.SaveChangesAsync();
+ }
- if ( !_dbContext.CredentialTypes.Any(p => p.Code == "email") )
- {
- _dbContext.CredentialTypes.Add(
- new CredentialType { Code = "email", Name = "t" });
- await _dbContext.SaveChangesAsync();
- }
+ var result = await userManager.ValidateAsync("email", "test", "test");
- var result = await userManager.ValidateAsync("email", "test", "test");
+ Assert.IsFalse(result.Success);
+ Assert.AreEqual(ValidateResultError.CredentialNotFound, result.Error);
+ }
- Assert.IsFalse(result.Success);
- Assert.AreEqual(ValidateResultError.CredentialNotFound, result.Error);
- }
+ [TestMethod]
+ public async Task ValidateAsync_User_NotFound()
+ {
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
- [TestMethod]
- public async Task ValidateAsync_User_NotFound()
+ var test = await _dbContext.CredentialTypes.AnyAsync(p => p.Code == "email");
+ if (!test)
{
- var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
- _memoryCache);
+ _dbContext.CredentialTypes.Add(
+ new CredentialType { Code = "email", Name = "T" });
+ await _dbContext.SaveChangesAsync();
+ }
- if ( !_dbContext.CredentialTypes.Any(p => p.Code == "email") )
- {
- _dbContext.CredentialTypes.Add(
- new CredentialType { Code = "email", Name = "T" });
- await _dbContext.SaveChangesAsync();
- }
+ var credentialTypesCode = await _dbContext.CredentialTypes.FirstOrDefaultAsync();
- var credentialTypesCode = _dbContext.CredentialTypes.FirstOrDefault();
+ _dbContext.Credentials.Add(new Credential
+ {
+ Identifier = "test_0005",
+ CredentialTypeId = credentialTypesCode!.Id,
+ Secret = "t5cJrj735BKTx6bNw2snWzkKb5lsXDSreT9Fpz5YLJw=", // "pass123456789" Iterate Legacy
+ Extra = "0kp9rQX22yeGPl3FSyZFlg=="
+ });
+ await _dbContext.SaveChangesAsync();
+
+ var result = await userManager.ValidateAsync(credentialTypesCode.Code!, "test_0005",
+ "pass123456789");
+
+ Assert.IsFalse(result.Success);
+ Assert.AreEqual(ValidateResultError.UserNotFound, result.Error);
+ }
- _dbContext.Credentials.Add(new Credential
- {
- Identifier = "test_0005",
- CredentialTypeId = credentialTypesCode!.Id,
- Secret = "t5cJrj735BKTx6bNw2snWzkKb5lsXDSreT9Fpz5YLJw=", // "pass123456789"
- Extra = "0kp9rQX22yeGPl3FSyZFlg=="
- });
+ [DataTestMethod] // [Theory]
+ [DataRow(true)]
+ [DataRow(false)]
+ public async Task ValidateAsync_Transform_To_Iterate100K(bool cacheEnabled)
+ {
+ var test = await _dbContext.CredentialTypes.AnyAsync(p => p.Code == "email");
+ if (!test)
+ {
+ _dbContext.CredentialTypes.Add(
+ new CredentialType { Code = "email", Name = "T" });
await _dbContext.SaveChangesAsync();
+ }
+ var credentialTypesCode = await _dbContext.CredentialTypes.FirstOrDefaultAsync();
- var result = await userManager.ValidateAsync(credentialTypesCode.Code!, "test_0005",
- "pass123456789");
+ await _dbContext.Users.AddAsync(new User
+ {
+ Name = "test_0008",
+ });
+ await _dbContext.SaveChangesAsync();
- Assert.IsFalse(result.Success);
- Assert.AreEqual(ValidateResultError.UserNotFound, result.Error);
+ var cred = new Credential
+ {
+ Identifier = "test_0008",
+ CredentialTypeId = credentialTypesCode!.Id,
+ CredentialType = credentialTypesCode,
+ Secret = "t5cJrj735BKTx6bNw2snWzkKb5lsXDSreT9Fpz5YLJw=", // "pass123456789" (IterateLegacy)
+ Extra = "0kp9rQX22yeGPl3FSyZFlg==",
+ IterationCount = IterationCountType.IterateLegacySha1,
+ User = await _dbContext.Users.FirstOrDefaultAsync(p => p.Name == "test_0008"),
+ UserId = ( await _dbContext.Users.FirstOrDefaultAsync(p => p.Name == "test_0008") )!.Id,
+ Id = 43579345
+ };
+ var credExists = await _dbContext.Credentials.AnyAsync(p => p.Identifier == "test_0008");
+ if ( !credExists )
+ {
+ _dbContext.Credentials.Add(cred);
+ await _dbContext.SaveChangesAsync();
+ _dbContext.Entry(cred).State = EntityState.Detached;
}
- [TestMethod]
- public async Task ValidateAsync_LockoutEnabled()
- {
- var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
- _memoryCache);
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ cacheEnabled ? _memoryCache: null);
+
+ var result = await userManager.ValidateAsync(credentialTypesCode.Code!, "test_0008",
+ "pass123456789");
+
+ var credAfterTransform = await _dbContext.Credentials
+ .FirstOrDefaultAsync(p => p.Identifier == "test_0008");
+
+ Assert.IsTrue(result.Success);
+ Assert.AreEqual("jCCNdJCtH6h1UBhEHkHawc+zt9PqQaEEubc8yc5CGTw=", credAfterTransform?.Secret);
+ Assert.AreEqual(IterationCountType.Iterate100KSha256, credAfterTransform?.IterationCount);
+ }
- await userManager.SignUpAsync("lockout@google.com", "email", "lockout@google.com",
- "pass");
+ [TestMethod]
+ public async Task ValidateAsync_LockoutEnabled()
+ {
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
- var userObject = _dbContext.Users.FirstOrDefault(p =>
- p.Name == "lockout@google.com");
+ await userManager.SignUpAsync("lockout@google.com", "email", "lockout@google.com",
+ "pass");
- userObject!.LockoutEnabled = true;
- userObject.LockoutEnd = DateTime.UtcNow.AddDays(1);
- await _dbContext.SaveChangesAsync();
+ var userObject = await _dbContext.Users.FirstOrDefaultAsync(p =>
+ p.Name == "lockout@google.com");
- var result =
- await userManager.ValidateAsync("email", "lockout@google.com",
- "--does not matter--");
+ userObject!.LockoutEnabled = true;
+ userObject.LockoutEnd = DateTime.UtcNow.AddDays(1);
+ await _dbContext.SaveChangesAsync();
- Assert.IsFalse(result.Success);
- Assert.AreEqual(ValidateResultError.Lockout, result.Error);
- }
+ var result =
+ await userManager.ValidateAsync("email", "lockout@google.com",
+ "--does not matter--");
- [TestMethod]
- public async Task ValidateAsync_3thTry()
- {
- var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
- _memoryCache);
+ Assert.IsFalse(result.Success);
+ Assert.AreEqual(ValidateResultError.Lockout, result.Error);
+ }
- await userManager.SignUpAsync("try3@google.com", "email", "try3@google.com", "pass");
+ [TestMethod]
+ public async Task ValidateAsync_3thTry()
+ {
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
- var userObject = _dbContext.Users.FirstOrDefault(p =>
- p.Name == "try3@google.com");
+ await userManager.SignUpAsync("try3@google.com", "email", "try3@google.com", "pass");
- userObject!.AccessFailedCount = 2;
- await _dbContext.SaveChangesAsync();
+ var userObject = await _dbContext.Users.FirstOrDefaultAsync(p =>
+ p.Name == "try3@google.com");
- var result =
- await userManager.ValidateAsync("email", "try3@google.com", "--does not matter--");
+ userObject!.AccessFailedCount = 2;
+ await _dbContext.SaveChangesAsync();
- Assert.IsFalse(result.Success);
- Assert.AreEqual(ValidateResultError.Lockout, result.Error);
- }
+ var result =
+ await userManager.ValidateAsync("email", "try3@google.com", "--does not matter--");
- [TestMethod]
- public async Task ValidateAsync_ResetCountAfterSuccessLogin()
- {
- var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
- _memoryCache);
+ Assert.IsFalse(result.Success);
+ Assert.AreEqual(ValidateResultError.Lockout, result.Error);
+ }
- await userManager.SignUpAsync("reset@google.com", "email", "reset@google.com", "pass");
+ [TestMethod]
+ public async Task ValidateAsync_ResetCountAfterSuccessLogin()
+ {
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
- var userObject = _dbContext.Users.FirstOrDefault(p =>
- p.Name == "reset@google.com");
+ await userManager.SignUpAsync("reset@google.com", "email", "reset@google.com", "pass");
- userObject!.AccessFailedCount = 2;
- await _dbContext.SaveChangesAsync();
+ var userObject = await _dbContext.Users.FirstOrDefaultAsync(p =>
+ p.Name == "reset@google.com");
- var result = await userManager.ValidateAsync("email", "reset@google.com", "pass");
+ userObject!.AccessFailedCount = 2;
+ await _dbContext.SaveChangesAsync();
- Assert.IsTrue(result.Success);
+ var result = await userManager.ValidateAsync("email", "reset@google.com", "pass");
- userObject = _dbContext.Users.FirstOrDefault(p =>
- p.Name == "reset@google.com");
+ Assert.IsTrue(result.Success);
- Assert.IsNotNull(userObject);
- Assert.IsNotNull(userObject.AccessFailedCount);
- Assert.AreEqual(0, userObject.AccessFailedCount);
- Assert.AreEqual(DateTime.MinValue, userObject.LockoutEnd);
- Assert.IsFalse(userObject.LockoutEnabled);
- }
+ userObject = await _dbContext.Users.FirstOrDefaultAsync(p =>
+ p.Name == "reset@google.com");
- [TestMethod]
- public async Task ValidateAsync_LockoutExpired()
- {
- var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
- _memoryCache);
+ Assert.IsNotNull(userObject);
+ Assert.IsNotNull(userObject.AccessFailedCount);
+ Assert.AreEqual(0, userObject.AccessFailedCount);
+ Assert.AreEqual(DateTime.MinValue, userObject.LockoutEnd);
+ Assert.IsFalse(userObject.LockoutEnabled);
+ }
- await userManager.SignUpAsync("lockout2@google.com", "email", "lockout2@google.com",
- "pass");
+ [TestMethod]
+ public async Task ValidateAsync_LockoutExpired()
+ {
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
- var userObject = _dbContext.Users.FirstOrDefault(p =>
- p.Name == "lockout2@google.com");
+ await userManager.SignUpAsync("lockout2@google.com", "email", "lockout2@google.com",
+ "pass");
- userObject!.LockoutEnabled = true;
- userObject.LockoutEnd = DateTime.UtcNow.AddDays(-2);
- await _dbContext.SaveChangesAsync();
+ var userObject = await _dbContext.Users.FirstOrDefaultAsync(p =>
+ p.Name == "lockout2@google.com");
- var result = await userManager.ValidateAsync("email", "lockout2@google.com", "pass");
+ userObject!.LockoutEnabled = true;
+ userObject.LockoutEnd = DateTime.UtcNow.AddDays(-2);
+ await _dbContext.SaveChangesAsync();
- Assert.IsTrue(result.Success);
- }
+ var result = await userManager.ValidateAsync("email", "lockout2@google.com", "pass");
- [TestMethod]
- public async Task UserManager_WrongPassword()
- {
- var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
- _memoryCache);
+ Assert.IsTrue(result.Success);
+ }
- await userManager.SignUpAsync("user01", "email", "test1@google.com", "pass");
+ [TestMethod]
+ public async Task UserManager_WrongPassword()
+ {
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
- var result = await userManager.ValidateAsync("email", "test1@google.com", "----");
- Assert.IsFalse(result.Success);
- Assert.AreEqual(ValidateResultError.SecretNotValid, result.Error);
+ await userManager.SignUpAsync("user01", "email", "test1@google.com", "pass");
- await userManager.RemoveUser("email", "test1@google.com");
- }
+ var result = await userManager.ValidateAsync("email", "test1@google.com", "----");
+ Assert.IsFalse(result.Success);
+ Assert.AreEqual(ValidateResultError.SecretNotValid, result.Error);
- [TestMethod]
- public async Task UserManager_LoginPassword_DefaultFlow()
- {
- var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
- _memoryCache);
+ await userManager.RemoveUser("email", "test1@google.com");
+ }
- await userManager.SignUpAsync("user02", "email", "login2@mail.us", "pass");
+ [TestMethod]
+ public async Task UserManager_LoginPassword_DefaultFlow()
+ {
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
- var result = await userManager.ValidateAsync("email", "login2@mail.us", "pass");
- Assert.IsTrue(result.Success);
+ await userManager.SignUpAsync("user02", "email", "login2@mail.us", "pass");
- await userManager.RemoveUser("email", "login2@mail.us");
- }
+ var result = await userManager.ValidateAsync("email", "login2@mail.us", "pass");
+ Assert.IsTrue(result.Success);
- [TestMethod]
- public async Task UserManager_LoginPassword_ShouldBeUser()
- {
- var userManager = new UserManager(_dbContext,
- new AppSettings
- {
- AccountRegisterDefaultRole = AccountRoles.AppAccountRoles.User,
- AccountRegisterFirstRoleAdmin = false
- }, new FakeIWebLogger(), _memoryCache);
+ await userManager.RemoveUser("email", "login2@mail.us");
+ }
- await userManager.SignUpAsync("user03", "email", "login3@mail.us", "pass");
+ [TestMethod]
+ public async Task UserManager_LoginPassword_ShouldBeUser()
+ {
+ var userManager = new UserManager(_dbContext,
+ new AppSettings
+ {
+ AccountRegisterDefaultRole = AccountRoles.AppAccountRoles.User,
+ AccountRegisterFirstRoleAdmin = false
+ }, new FakeIWebLogger(), _memoryCache);
- var result = userManager.GetRole("email", "login3@mail.us");
- Assert.IsNotNull(result);
- Assert.IsNotNull(result.Code);
- Assert.AreEqual(AccountRoles.AppAccountRoles.User.ToString(), result.Code);
+ await userManager.SignUpAsync("user03", "email", "login3@mail.us", "pass");
- await userManager.RemoveUser("email", "login3@mail.us");
- }
+ var result = userManager.GetRole("email", "login3@mail.us");
+ Assert.IsNotNull(result);
+ Assert.IsNotNull(result.Code);
+ Assert.AreEqual(AccountRoles.AppAccountRoles.User.ToString(), result.Code);
- [TestMethod]
- public async Task UserManager_LoginPassword_ShouldBeAdminDueFirstPolicy()
- {
- var builder = new DbContextOptionsBuilder();
- builder.UseInMemoryDatabase(nameof(MetaUpdateService) + "_test");
- var options = builder.Options;
- var dbContext = new ApplicationDbContext(options);
-
- var userManager = new UserManager(dbContext,
- new AppSettings
- {
- AccountRegisterDefaultRole = AccountRoles.AppAccountRoles.User,
- AccountRegisterFirstRoleAdmin = true
- }, new FakeIWebLogger(), _memoryCache);
-
- await userManager.SignUpAsync("user04", "email", "login@mail.us", "pass");
-
- var result = userManager.GetRole("email", "login@mail.us");
- Assert.AreEqual(AccountRoles.AppAccountRoles.Administrator.ToString(), result?.Code);
- }
+ await userManager.RemoveUser("email", "login3@mail.us");
+ }
+ [TestMethod]
+ public async Task UserManager_LoginPassword_ShouldBeAdminDueFirstPolicy()
+ {
+ var builder = new DbContextOptionsBuilder();
+ builder.UseInMemoryDatabase(nameof(MetaUpdateService) + "_test");
+ var options = builder.Options;
+ var dbContext = new ApplicationDbContext(options);
- [TestMethod]
- public async Task UserManager_LoginPassword_ShouldUser_second()
- {
- var userManager = new UserManager(_dbContext,
- new AppSettings
- {
- AccountRegisterDefaultRole = AccountRoles.AppAccountRoles.User,
- AccountRegisterFirstRoleAdmin = true
- }, new FakeIWebLogger(), _memoryCache);
-
- foreach ( var user in _dbContext.Users.Include(p => p.Credentials)
- .Where(p => p.Credentials != null && p.Credentials.Count != 0)
- .ToList() )
+ var userManager = new UserManager(dbContext,
+ new AppSettings
{
- await userManager.RemoveUser("email",
- user.Credentials!.FirstOrDefault()!.Identifier!);
- }
+ AccountRegisterDefaultRole = AccountRoles.AppAccountRoles.User,
+ AccountRegisterFirstRoleAdmin = true
+ }, new FakeIWebLogger(), _memoryCache);
- await userManager.SignUpAsync("user01", "email", "login@mail.us", "pass");
- await userManager.SignUpAsync("user02", "email", "login@mail2.us", "pass");
+ await userManager.SignUpAsync("user04", "email", "login@mail.us", "pass");
- var result = userManager.GetRole("email", "login@mail2.us");
+ var result = userManager.GetRole("email", "login@mail.us");
+ Assert.AreEqual(AccountRoles.AppAccountRoles.Administrator.ToString(), result?.Code);
+ }
- Assert.IsNotNull(result);
- Assert.IsNotNull(result.Code);
- Assert.AreEqual(AccountRoles.AppAccountRoles.User.ToString(), result.Code);
- }
+ [TestMethod]
+ public async Task UserManager_LoginPassword_ShouldUser_second()
+ {
+ var userManager = new UserManager(_dbContext,
+ new AppSettings
+ {
+ AccountRegisterDefaultRole = AccountRoles.AppAccountRoles.User,
+ AccountRegisterFirstRoleAdmin = true
+ }, new FakeIWebLogger(), _memoryCache);
- [TestMethod]
- public async Task UserManager_LoginNull_Identifier()
+ foreach ( var user in await _dbContext.Users.Include(p => p.Credentials)
+ .Where(p => p.Credentials != null && p.Credentials.Count != 0)
+ .ToListAsync() )
{
- var userManager = new UserManager(_dbContext,
- new AppSettings
- {
- AccountRegisterDefaultRole = AccountRoles.AppAccountRoles.User,
- AccountRegisterFirstRoleAdmin = true
- }, new FakeIWebLogger(), _memoryCache);
+ await userManager.RemoveUser("email",
+ user.Credentials!.FirstOrDefault()!.Identifier!);
+ }
- var result = await userManager.SignUpAsync("user01", "email", string.Empty, "pass");
+ await userManager.SignUpAsync("user01", "email", "login@mail.us", "pass");
+ await userManager.SignUpAsync("user02", "email", "login@mail2.us", "pass");
- Assert.AreEqual(SignUpResultError.NullString, result.Error);
- }
+ var result = userManager.GetRole("email", "login@mail2.us");
- [TestMethod]
- public async Task UserManager_LoginNull_Secret()
- {
- var userManager = new UserManager(_dbContext,
- new AppSettings
- {
- AccountRegisterDefaultRole = AccountRoles.AppAccountRoles.User,
- AccountRegisterFirstRoleAdmin = true
- }, new FakeIWebLogger(), _memoryCache);
+ Assert.IsNotNull(result);
+ Assert.IsNotNull(result.Code);
+ Assert.AreEqual(AccountRoles.AppAccountRoles.User.ToString(), result.Code);
+ }
- var result =
- await userManager.SignUpAsync("user01", "email", "dont@mail.me", string.Empty);
+ [TestMethod]
+ public async Task UserManager_LoginNull_Identifier()
+ {
+ var userManager = new UserManager(_dbContext,
+ new AppSettings
+ {
+ AccountRegisterDefaultRole = AccountRoles.AppAccountRoles.User,
+ AccountRegisterFirstRoleAdmin = true
+ }, new FakeIWebLogger(), _memoryCache);
- Assert.AreEqual(SignUpResultError.NullString, result.Error);
- }
+ var result = await userManager.SignUpAsync("user01", "email", string.Empty, "pass");
- [TestMethod]
- public async Task UserManager_Login_CredentialTypeNotFound()
- {
- var userManager = new UserManager(_dbContext,
- new AppSettings
- {
- AccountRegisterDefaultRole = AccountRoles.AppAccountRoles.User,
- AccountRegisterFirstRoleAdmin = true
- }, new FakeIWebLogger(), _memoryCache);
+ Assert.AreEqual(SignUpResultError.NullString, result.Error);
+ }
- var result =
- await userManager.SignUpAsync("user01", "wrong-type1", "dont@mail.me", "122344");
+ [TestMethod]
+ public async Task UserManager_LoginNull_Secret()
+ {
+ var userManager = new UserManager(_dbContext,
+ new AppSettings
+ {
+ AccountRegisterDefaultRole = AccountRoles.AppAccountRoles.User,
+ AccountRegisterFirstRoleAdmin = true
+ }, new FakeIWebLogger(), _memoryCache);
- Assert.AreEqual(SignUpResultError.CredentialTypeNotFound, result.Error);
- }
+ var result =
+ await userManager.SignUpAsync("user01", "email", "dont@mail.me", string.Empty);
- [TestMethod]
- public async Task UserManager_ChangePassword_ChangeSecret()
- {
- var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
- _memoryCache);
+ Assert.AreEqual(SignUpResultError.NullString, result.Error);
+ }
- await userManager.SignUpAsync("user01", "email", "dont@mail.us", "pass123456789");
+ [TestMethod]
+ public async Task UserManager_Login_CredentialTypeNotFound()
+ {
+ var userManager = new UserManager(_dbContext,
+ new AppSettings
+ {
+ AccountRegisterDefaultRole = AccountRoles.AppAccountRoles.User,
+ AccountRegisterFirstRoleAdmin = true
+ }, new FakeIWebLogger(), _memoryCache);
- var result = userManager.ChangeSecret("email", "dont@mail.us", "pass123456789");
+ var result =
+ await userManager.SignUpAsync("user01", "wrong-type1", "dont@mail.me", "122344");
- Assert.IsTrue(result.Success);
- }
+ Assert.AreEqual(SignUpResultError.CredentialTypeNotFound, result.Error);
+ }
- [TestMethod]
- public void ChangeSecret_Credential_WrongTypeCode()
- {
- var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
- _memoryCache);
+ [TestMethod]
+ public async Task UserManager_ChangePassword_ChangeSecret()
+ {
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
- var result = userManager.ChangeSecret("wrong-type", "dont@mail.us", "pass123456789");
+ await userManager.SignUpAsync("user01", "email", "dont@mail.us", "pass123456789");
- Assert.AreEqual(ChangeSecretResultError.CredentialTypeNotFound, result.Error);
- }
+ var result = userManager.ChangeSecret("email", "dont@mail.us", "pass123456789");
- [TestMethod]
- public async Task ChangeSecret_Credential_NotFound()
- {
- var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
- _memoryCache);
+ Assert.IsTrue(result.Success);
+ }
- _dbContext.CredentialTypes.Add(
- new CredentialType { Code = "email", Name = "email", Id = 99 });
- await _dbContext.SaveChangesAsync();
+ [TestMethod]
+ public void ChangeSecret_Credential_WrongTypeCode()
+ {
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
- var result =
- userManager.ChangeSecret("email", "fdksdnfdsfl@sdnklffsd.com", "pass123456789");
+ var result = userManager.ChangeSecret("wrong-type", "dont@mail.us", "pass123456789");
+ Assert.AreEqual(ChangeSecretResultError.CredentialTypeNotFound, result.Error);
+ }
- var emailType = _dbContext.CredentialTypes.FirstOrDefault(p => p.Code == "email");
- _dbContext.Remove(emailType!);
+ [TestMethod]
+ public async Task ChangeSecret_Credential_NotFound()
+ {
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
- await _dbContext.SaveChangesAsync();
+ _dbContext.CredentialTypes.Add(
+ new CredentialType { Code = "email", Name = "email", Id = 99 });
+ await _dbContext.SaveChangesAsync();
- Assert.AreEqual(ChangeSecretResultError.CredentialNotFound, result.Error);
- }
+ var result =
+ userManager.ChangeSecret("email", "fdksdnfdsfl@sdnklffsd.com", "pass123456789");
- [TestMethod]
- public async Task UserManager_NoPassword_ExistingAccount()
- {
- var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
- _memoryCache);
- await userManager.SignUpAsync("user02", "email", "dont@mail.us", "pass");
+ var emailType = await _dbContext.CredentialTypes.FirstOrDefaultAsync(p => p.Code == "email");
+ _dbContext.Remove(emailType!);
- var result = await userManager.ValidateAsync("email", "dont@mail.us", null!);
- Assert.IsFalse(result.Success);
- }
+ await _dbContext.SaveChangesAsync();
- [TestMethod]
- public async Task UserManager_AllUsers_testCache()
- {
- var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
- _memoryCache);
- await userManager.AddUserToCache(new User { Name = "cachedUser" });
+ Assert.AreEqual(ChangeSecretResultError.CredentialNotFound, result.Error);
+ }
- var user =
- ( await userManager.AllUsersAsync() ).Users.Find(p => p.Name == "cachedUser");
- Assert.IsNotNull(user);
- }
+ [TestMethod]
+ public async Task UserManager_NoPassword_ExistingAccount()
+ {
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
+ await userManager.SignUpAsync("user02", "email", "dont@mail.us", "pass");
- private class AppDbContextRetryLimitExceededException : ApplicationDbContext
- {
- public AppDbContextRetryLimitExceededException(DbContextOptions options) : base(options)
- {
- }
+ var result = await userManager.ValidateAsync("email", "dont@mail.us", null!);
+ Assert.IsFalse(result.Success);
+ }
- public override DbSet Users => throw new RetryLimitExceededException("general");
- }
+ [TestMethod]
+ public async Task UserManager_AllUsers_testCache()
+ {
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
+ await userManager.AddUserToCache(new User { Name = "cachedUser" });
- [TestMethod]
- public async Task UserManager_AllUsers_RetryException()
- {
- var logger = new FakeIWebLogger();
- var options = new DbContextOptionsBuilder()
- .UseInMemoryDatabase(databaseName: "MovieListDatabase")
- .Options;
-
- var userManager = new UserManager(new AppDbContextRetryLimitExceededException(options),
- new AppSettings(), logger, new FakeMemoryCache());
- var users = ( await userManager.AllUsersAsync() ).Users;
-
- Assert.AreEqual(0, users.Count);
- Assert.IsTrue(logger.TrackedExceptions.LastOrDefault().Item2
- ?.Contains("RetryLimitExceededException") == true);
- }
+ var user =
+ ( await userManager.AllUsersAsync() ).Users.Find(p => p.Name == "cachedUser");
+ Assert.IsNotNull(user);
+ }
- [TestMethod]
- public async Task UserManager_RemoveUser()
- {
- var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
- _memoryCache);
+ private class AppDbContextRetryLimitExceededException(DbContextOptions options)
+ : ApplicationDbContext(options)
+ {
+ public override DbSet Users => throw new RetryLimitExceededException("general");
+ }
- await userManager.SignUpAsync("to_remove", "email", "to_remove@mail.us",
- "pass123456789");
+ [TestMethod]
+ public async Task UserManager_AllUsers_RetryException()
+ {
+ var logger = new FakeIWebLogger();
+ var options = new DbContextOptionsBuilder()
+ .UseInMemoryDatabase(databaseName: "MovieListDatabase")
+ .Options;
+
+ var userManager = new UserManager(new AppDbContextRetryLimitExceededException(options),
+ new AppSettings(), logger, new FakeMemoryCache());
+ var users = ( await userManager.AllUsersAsync() ).Users;
+
+ Assert.AreEqual(0, users.Count);
+ Assert.IsTrue(logger.TrackedExceptions.LastOrDefault().Item2
+ ?.Contains("RetryLimitExceededException") == true);
+ }
- var result = await userManager.RemoveUser("email", "to_remove@mail.us");
+ [TestMethod]
+ public async Task UserManager_RemoveUser()
+ {
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
- Assert.IsTrue(result.Success);
+ await userManager.SignUpAsync("to_remove", "email", "to_remove@mail.us",
+ "pass123456789");
- var user = ( await userManager.AllUsersAsync() ).Users.Find(p => p.Name == "to_remove");
- Assert.IsNull(user);
- }
+ var result = await userManager.RemoveUser("email", "to_remove@mail.us");
+ Assert.IsTrue(result.Success);
- [TestMethod]
- public async Task UserManager_RemoveUser_NonExistsCredType()
- {
- var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
- _memoryCache);
+ var user = ( await userManager.AllUsersAsync() ).Users.Find(p => p.Name == "to_remove");
+ Assert.IsNull(user);
+ }
- var result = await userManager.RemoveUser("___email___", "non_exists@mail.us");
+ [TestMethod]
+ public async Task UserManager_RemoveUser_NonExistsCredType()
+ {
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
- Assert.IsFalse(result.Success);
- }
+ var result = await userManager.RemoveUser("___email___", "non_exists@mail.us");
- [TestMethod]
- public async Task UserManager_RemoveUser_NonExists()
- {
- var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
- _memoryCache);
- await userManager.AddDefaultCredentialType("email");
+ Assert.IsFalse(result.Success);
+ }
- var result = await userManager.RemoveUser("email", "non_exists@mail.us");
+ [TestMethod]
+ public async Task UserManager_RemoveUser_NonExists()
+ {
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
+ await userManager.AddDefaultCredentialType("email");
- Assert.IsFalse(result.Success);
- }
+ var result = await userManager.RemoveUser("email", "non_exists@mail.us");
- [TestMethod]
- public async Task AddToRole()
- {
- var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
- _memoryCache);
- await userManager.SignUpAsync("AddToRole", "email", "AddToRole@mail.us",
- "pass123456789");
+ Assert.IsFalse(result.Success);
+ }
- var user = userManager.GetUser("email", "AddToRole@mail.us");
- Assert.IsNotNull(user);
+ [TestMethod]
+ public async Task AddToRole()
+ {
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
+ await userManager.SignUpAsync("AddToRole", "email", "AddToRole@mail.us",
+ "pass123456789");
- // Default role is User
- userManager.RemoveFromRole(user, AccountRoles.AppAccountRoles.User.ToString());
+ var user = userManager.GetUser("email", "AddToRole@mail.us");
+ Assert.IsNotNull(user);
- // Now add the Admin role
- userManager.AddToRole(user, AccountRoles.AppAccountRoles.Administrator.ToString());
+ // Default role is User
+ userManager.RemoveFromRole(user, AccountRoles.AppAccountRoles.User.ToString());
- var result = userManager.GetRole("email", "AddToRole@mail.us");
+ // Now add the Admin role
+ userManager.AddToRole(user, AccountRoles.AppAccountRoles.Administrator.ToString());
- Assert.IsNotNull(result);
- Assert.AreEqual(AccountRoles.AppAccountRoles.Administrator.ToString(), result.Code);
- }
+ var result = userManager.GetRole("email", "AddToRole@mail.us");
+ Assert.IsNotNull(result);
+ Assert.AreEqual(AccountRoles.AppAccountRoles.Administrator.ToString(), result.Code);
+ }
- [TestMethod]
- public void AddToRole_WrongCode()
- {
- var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
- _memoryCache);
- var count = _dbContext.Roles.Count();
- userManager.AddToRole(new User(), "test123");
+ [TestMethod]
+ public void AddToRole_WrongCode()
+ {
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
+ var count = _dbContext.Roles.Count();
+ userManager.AddToRole(new User(), "test123");
- Assert.AreEqual(count, _dbContext.Roles.Count());
- }
+ Assert.AreEqual(count, _dbContext.Roles.Count());
+ }
- [TestMethod]
- public void GetRole_NotExists()
- {
- var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
- _memoryCache);
- var result = userManager.GetRole("test12", "test");
- Assert.IsNull(result);
- }
+ [TestMethod]
+ public void GetRole_NotExists()
+ {
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
+ var result = userManager.GetRole("test12", "test");
+ Assert.IsNull(result);
+ }
- [TestMethod]
- public async Task GetRoleAsync_NotExists()
- {
- var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
- _memoryCache);
- var result = await userManager.GetRoleAsync(453454);
- Assert.IsNull(result);
- }
+ [TestMethod]
+ public async Task GetRoleAsync_NotExists()
+ {
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
+ var result = await userManager.GetRoleAsync(453454);
+ Assert.IsNull(result);
+ }
- [TestMethod]
- public async Task GetRoleAsync_Exists()
+ [TestMethod]
+ public async Task GetRoleAsync_Exists()
+ {
+ _dbContext.Users.Add(new User { Id = 45475, Name = "test" });
+ _dbContext.Roles.Add(new Role
{
- _dbContext.Users.Add(new User { Id = 45475, Name = "test" });
- _dbContext.Roles.Add(new Role
- {
- Code = "test_role_892453", Name = "test", Id = 47583945
- });
- _dbContext.UserRoles.Add(new UserRole { UserId = 45475, RoleId = 47583945 });
-
- await _dbContext.SaveChangesAsync();
- var role =
- await _dbContext.Roles.FirstOrDefaultAsync(p => p.Code == "test_role_892453");
- var userRole =
- await _dbContext.UserRoles.FirstOrDefaultAsync(p => p.UserId == 45475);
- var user =
- await _dbContext.Users.FirstOrDefaultAsync(p => p.Id == 45475);
- Assert.IsNotNull(role);
- Assert.IsNotNull(userRole);
- Assert.IsNotNull(user);
-
- var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
- _memoryCache);
- var result = await userManager.GetRoleAsync(45475);
-
- Assert.AreEqual("test_role_892453", result?.Code);
-
- _dbContext.Remove(role);
- _dbContext.Remove(userRole);
- _dbContext.Remove(user);
+ Code = "test_role_892453", Name = "test", Id = 47583945
+ });
+ _dbContext.UserRoles.Add(new UserRole { UserId = 45475, RoleId = 47583945 });
+
+ await _dbContext.SaveChangesAsync();
+ var role =
+ await _dbContext.Roles.FirstOrDefaultAsync(p => p.Code == "test_role_892453");
+ var userRole =
+ await _dbContext.UserRoles.FirstOrDefaultAsync(p => p.UserId == 45475);
+ var user =
+ await _dbContext.Users.FirstOrDefaultAsync(p => p.Id == 45475);
+ Assert.IsNotNull(role);
+ Assert.IsNotNull(userRole);
+ Assert.IsNotNull(user);
+
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
+ var result = await userManager.GetRoleAsync(45475);
+
+ Assert.AreEqual("test_role_892453", result?.Code);
+
+ _dbContext.Remove(role);
+ _dbContext.Remove(userRole);
+ _dbContext.Remove(user);
+
+ await _dbContext.SaveChangesAsync();
+ }
- await _dbContext.SaveChangesAsync();
- }
+ [TestMethod]
+ public async Task RemoveFromRole()
+ {
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
+ await userManager.SignUpAsync("RemoveFromRole", "email", "RemoveFromRole@mail.us",
+ "pass123456789");
- [TestMethod]
- public async Task RemoveFromRole()
- {
- var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
- _memoryCache);
- await userManager.SignUpAsync("RemoveFromRole", "email", "RemoveFromRole@mail.us",
- "pass123456789");
+ var user = userManager.GetUser("email", "RemoveFromRole@mail.us");
+ Assert.IsNotNull(user);
- var user = userManager.GetUser("email", "RemoveFromRole@mail.us");
- Assert.IsNotNull(user);
+ // Default role is User
+ userManager.RemoveFromRole(user, AccountRoles.AppAccountRoles.User.ToString());
- // Default role is User
- userManager.RemoveFromRole(user, AccountRoles.AppAccountRoles.User.ToString());
+ var result = userManager.GetRole("email", "RemoveFromRole@mail.us");
- var result = userManager.GetRole("email", "RemoveFromRole@mail.us");
+ Assert.IsNotNull(result);
+ Assert.IsNull(result.Code);
+ }
- Assert.IsNotNull(result);
- Assert.IsNull(result.Code);
- }
+ [TestMethod]
+ public void RemoveFromRole_WrongCode()
+ {
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
+ var count = _dbContext.Roles.Count();
+ userManager.RemoveFromRole(new User(), "test");
+ Assert.AreEqual(count, _dbContext.Roles.Count());
+ }
+
+ [TestMethod]
+ public void RemoveFromRole_WrongCode_RoleObject()
+ {
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
+ var count = _dbContext.Roles.Count();
+ var role = new Role();
+ userManager.RemoveFromRole(new User(), role);
- [TestMethod]
- public void RemoveFromRole_WrongCode()
- {
- var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
- _memoryCache);
- var count = _dbContext.Roles.Count();
- userManager.RemoveFromRole(new User(), "test");
+ Assert.AreEqual(count, _dbContext.Roles.Count());
+ }
- Assert.AreEqual(count, _dbContext.Roles.Count());
- }
+ [TestMethod]
+ public async Task GetUser()
+ {
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
+ await userManager.SignUpAsync("GetUser", "email", "GetUser@mail.us", "pass123456789");
- [TestMethod]
- public async Task GetUser()
- {
- var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
- _memoryCache);
- await userManager.SignUpAsync("GetUser", "email", "GetUser@mail.us", "pass123456789");
+ var user = userManager.GetUser("email", "GetUser@mail.us");
- var user = userManager.GetUser("email", "GetUser@mail.us");
+ Assert.IsNotNull(user);
+ Assert.AreEqual("GetUser", user.Name);
+ }
- Assert.IsNotNull(user);
- Assert.AreEqual("GetUser", user.Name);
- }
+ [TestMethod]
+ public void GetUser_credentialTypeNull_IdDoesNotExist()
+ {
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
+ var user = userManager.GetUser("email", "sfkknfdlknsdfl@mail.us");
+ Assert.IsNull(user);
+ }
- [TestMethod]
- public void GetUser_credentialTypeNull_IdDoesNotExist()
- {
- var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
- _memoryCache);
- var user = userManager.GetUser("email", "sfkknfdlknsdfl@mail.us");
- Assert.IsNull(user);
- }
+ [TestMethod]
+ public async Task GetUser_IdDoesNotExist()
+ {
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
+ await userManager.AddDefaultCredentialType("email");
+ var user = userManager.GetUser("email", "sfkknfdlknsdfl@mail.us");
+ Assert.IsNull(user);
+ }
- [TestMethod]
- public async Task GetUser_IdDoesNotExist()
- {
- var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
- _memoryCache);
- await userManager.AddDefaultCredentialType("email");
- var user = userManager.GetUser("email", "sfkknfdlknsdfl@mail.us");
- Assert.IsNull(user);
- }
+ [TestMethod]
+ public void PreflightValidate_Fail_stringEmpty()
+ {
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
+ Assert.IsFalse(userManager.PreflightValidate(string.Empty, string.Empty, string.Empty));
+ }
+ [TestMethod]
+ public void PreflightValidate_Fail_wrongEmail()
+ {
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
+ Assert.IsFalse(userManager.PreflightValidate("no_mail", "123456789012345",
+ "123456789012345"));
+ }
- [TestMethod]
- public void PreflightValidate_Fail_stringEmpty()
- {
- var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
- _memoryCache);
- Assert.IsFalse(userManager.PreflightValidate(string.Empty, string.Empty, string.Empty));
- }
+ [TestMethod]
+ public void PreflightValidate_Ok()
+ {
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
+ Assert.IsTrue(userManager.PreflightValidate("dont@mail.me", "123456789012345",
+ "123456789012345"));
+ }
- [TestMethod]
- public void PreflightValidate_Fail_wrongEmail()
+ [TestMethod]
+ public void GetCurrentUserId_NotLoggedIn()
+ {
+ var context = new DefaultHttpContext();
+ var currentUserId = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache)
+ .GetCurrentUserId(context);
+ Assert.AreEqual(-1, currentUserId);
+ }
+
+ [TestMethod]
+ public void GetCurrentUserId_NotLoggedIn2()
+ {
+ var context = new DefaultHttpContext
{
- var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
- _memoryCache);
- Assert.IsFalse(userManager.PreflightValidate("no_mail", "123456789012345",
- "123456789012345"));
- }
+ User = new ClaimsPrincipal()
+ };
+ var currentUserId = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache)
+ .GetCurrentUserId(context);
+ Assert.AreEqual(-1, currentUserId);
+ }
- [TestMethod]
- public void PreflightValidate_Ok()
- {
- var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
- _memoryCache);
- Assert.IsTrue(userManager.PreflightValidate("dont@mail.me", "123456789012345",
- "123456789012345"));
- }
+ [TestMethod]
+ public void CachedCredential_NoId()
+ {
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
+ var cachedCredential = userManager.CachedCredential(null!, string.Empty);
+ Assert.IsNull(cachedCredential);
+ }
- [TestMethod]
- public void GetCurrentUserId_NotLoggedIn()
- {
- var context = new DefaultHttpContext();
- var currentUserId = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
- _memoryCache)
- .GetCurrentUserId(context);
- Assert.AreEqual(-1, currentUserId);
- }
+ [TestMethod]
+ public async Task CachedCredential_CheckCache()
+ {
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
+ var credType = new CredentialType { Id = 15, Code = "email1", Name = "1" };
- [TestMethod]
- public async Task CachedCredential_CheckCache()
- {
- var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
- _memoryCache);
- var credType = new CredentialType { Id = 15, Code = "email1", Name = "1" };
+ _memoryCache.Remove(UserManager.CredentialCacheKey(credType, "test_cache_add"));
- _memoryCache.Remove(UserManager.CredentialCacheKey(credType, "test_cache_add"));
+ await _dbContext.CredentialTypes.AddAsync(credType);
+ await _dbContext.SaveChangesAsync();
- await _dbContext.CredentialTypes.AddAsync(credType);
- await _dbContext.SaveChangesAsync();
+ await userManager.SignUpAsync("test", "email1", "test_cache_add",
+ "secret");
- await userManager.SignUpAsync("test", "email1", "test_cache_add",
- "secret");
+ // set cache with values
+ userManager.CachedCredential(credType,
+ "test_cache_add");
- // set cache with values
- userManager.CachedCredential(credType,
- "test_cache_add");
+ // Update Database
+ var cred =
+ await _dbContext.Credentials.FirstOrDefaultAsync(p =>
+ p.Identifier == "test_cache_add");
+ cred!.Identifier = "test_cache_add_1";
+ var expectSecret = cred.Secret;
+ _dbContext.Credentials.Update(cred);
+ await _dbContext.SaveChangesAsync();
- // Update Database
- var cred =
- _dbContext.Credentials.FirstOrDefault(p =>
- p.Identifier == "test_cache_add");
- cred!.Identifier = "test_cache_add_1";
- var expectSecret = cred.Secret;
- _dbContext.Credentials.Update(cred);
- await _dbContext.SaveChangesAsync();
+ // check cache again
+ var result = userManager.CachedCredential(credType,
+ "test_cache_add");
- // check cache again
- var result = userManager.CachedCredential(credType,
- "test_cache_add");
+ Assert.IsNotNull(result);
+ Assert.AreEqual(expectSecret, result.Secret);
+ }
- Assert.IsNotNull(result);
- Assert.AreEqual(expectSecret, result.Secret);
- }
+ [TestMethod]
+ public void GetUserPermissionClaims_ShouldGet()
+ {
+ _dbContext.RolePermissions.Add(new RolePermission { RoleId = 99, PermissionId = 101 });
- [TestMethod]
- public void GetUserPermissionClaims_ShouldGet()
- {
- _dbContext.RolePermissions.Add(new RolePermission { RoleId = 99, PermissionId = 101 });
+ _dbContext.Permissions.Add(new Permission { Id = 101, Code = "test", Name = "t" });
+ _dbContext.SaveChanges();
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
+ var result = userManager.GetUserPermissionClaims(new Role { Id = 99 }).ToList();
- _dbContext.Permissions.Add(new Permission { Id = 101, Code = "test", Name = "t" });
- _dbContext.SaveChanges();
- var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
- _memoryCache);
- var result = userManager.GetUserPermissionClaims(new Role { Id = 99 }).ToList();
+ Assert.AreEqual(1, result.Count);
+ Assert.AreEqual("test", result[0].Value);
+ }
- Assert.AreEqual(1, result.Count);
- Assert.AreEqual("test", result[0].Value);
- }
+ [TestMethod]
+ public async Task Cache_ExistsByUserTableId_HitResult()
+ {
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
+ await userManager.AddUserToCache(new User { Name = "cachedUser", Id = 1 });
- [TestMethod]
- public async Task Cache_ExistsByUserTableId_HitResult()
- {
- var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
- _memoryCache);
- await userManager.AddUserToCache(new User { Name = "cachedUser", Id = 1 });
+ var result = await userManager.ExistAsync(1);
- var result = await userManager.ExistAsync(1);
+ Assert.IsNotNull(result);
+ }
- Assert.IsNotNull(result);
- }
+ [TestMethod]
+ public async Task Cache_ExistsByUserTableId_NotFound()
+ {
+ var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
+ _memoryCache);
+ await userManager.AddUserToCache(new User { Name = "cachedUser", Id = 1 });
- [TestMethod]
- public async Task Cache_ExistsByUserTableId_NotFound()
- {
- var userManager = new UserManager(_dbContext, new AppSettings(), new FakeIWebLogger(),
- _memoryCache);
- await userManager.AddUserToCache(new User { Name = "cachedUser", Id = 1 });
+ var result = await userManager.ExistAsync(9822);
- var result = await userManager.ExistAsync(9822);
+ Assert.IsNull(result);
+ }
- Assert.IsNull(result);
- }
+ [TestMethod]
+ public async Task Db_ExistsByUserTableId_HitResult()
+ {
+ var userManager = new UserManager(_dbContext,
+ new AppSettings { AddMemoryCache = false }, new FakeIWebLogger(), _memoryCache);
+ var id = await userManager.SignUpAsync(string.Empty, "email", "t", "t");
+ Assert.IsNotNull(id);
+ Assert.IsNotNull(id.User);
- [TestMethod]
- public async Task Db_ExistsByUserTableId_HitResult()
- {
- var userManager = new UserManager(_dbContext,
- new AppSettings { AddMemoryCache = false }, new FakeIWebLogger(), _memoryCache);
- var id = await userManager.SignUpAsync(string.Empty, "email", "t", "t");
- Assert.IsNotNull(id);
- Assert.IsNotNull(id.User);
+ var result = await userManager.ExistAsync(id.User.Id);
- var result = await userManager.ExistAsync(id.User.Id);
+ Assert.IsNotNull(result);
+ }
- Assert.IsNotNull(result);
- }
+ [TestMethod]
+ public async Task Db_ExistsByUserTableId_NotFound()
+ {
+ var userManager = new UserManager(_dbContext,
+ new AppSettings { AddMemoryCache = false }, new FakeIWebLogger(), _memoryCache);
- [TestMethod]
- public async Task Db_ExistsByUserTableId_NotFound()
- {
- var userManager = new UserManager(_dbContext,
- new AppSettings { AddMemoryCache = false }, new FakeIWebLogger(), _memoryCache);
+ var result = await userManager.ExistAsync(852);
- var result = await userManager.ExistAsync(852);
+ Assert.IsNull(result);
+ }
- Assert.IsNull(result);
- }
+ [TestMethod]
+ public async Task ResetAndSuccessTest()
+ {
+ var userManager = new UserManager(_dbContext,
+ new AppSettings { AddMemoryCache = false }, new FakeIWebLogger(), _memoryCache);
+ var result = await userManager.ResetAndSuccess(3, 999, null);
+ Assert.IsFalse(result.Success);
+ }
- [TestMethod]
- public async Task ResetAndSuccessTest()
- {
- var userManager = new UserManager(_dbContext,
- new AppSettings { AddMemoryCache = false }, new FakeIWebLogger(), _memoryCache);
- var result = await userManager.ResetAndSuccess(3, 999, null);
- Assert.IsFalse(result.Success);
- }
+ [TestMethod]
+ public async Task SetLockIfFailCountIsToHighTest()
+ {
+ var userManager = new UserManager(_dbContext,
+ new AppSettings { AddMemoryCache = false }, new FakeIWebLogger(), _memoryCache);
+ var result = await userManager.SetLockIfFailedCountIsToHigh(9999);
+ Assert.IsFalse(result.Success);
+ }
- [TestMethod]
- public async Task SetLockIfFailCountIsToHighTest()
- {
- var userManager = new UserManager(_dbContext,
- new AppSettings { AddMemoryCache = false }, new FakeIWebLogger(), _memoryCache);
- var result = await userManager.SetLockIfFailedCountIsToHigh(9999);
- Assert.IsFalse(result.Success);
- }
+ [TestMethod]
+ public async Task UserManager_GetRoleAddToUser_Administrator()
+ {
+ var beforeItem = new User() { Name = "test1234567" };
+ await _dbContext.Users.AddAsync(beforeItem);
+ await _dbContext.SaveChangesAsync();
- [TestMethod]
- public async Task UserManager_GetRoleAddToUser_Administrator()
+ const string testEmail = "dont@mail.me";
+ var userManager = new UserManager(_dbContext, new AppSettings
{
- var beforeItem = new User() { Name = "test1234567" };
- await _dbContext.Users.AddAsync(beforeItem);
- await _dbContext.SaveChangesAsync();
-
- const string testEmail = "dont@mail.me";
- var userManager = new UserManager(_dbContext, new AppSettings
- {
- AddMemoryCache = false,
- AccountRegisterFirstRoleAdmin = false,
- AccountRegisterDefaultRole = AccountRoles.AppAccountRoles.User,
+ AddMemoryCache = false,
+ AccountRegisterFirstRoleAdmin = false,
+ AccountRegisterDefaultRole = AccountRoles.AppAccountRoles.User,
#pragma warning disable CS8670 // Object or collection initializer implicitly dereferences possibly null member.
- AccountRolesByEmailRegisterOverwrite = { { testEmail, "Administrator" } }
+ AccountRolesByEmailRegisterOverwrite = { { testEmail, "Administrator" } }
#pragma warning restore CS8670 // Object or collection initializer implicitly dereferences possibly null member.
- }, new FakeIWebLogger(), _memoryCache);
+ }, new FakeIWebLogger(), _memoryCache);
- var roleAddToUser = userManager.GetRoleAddToUser(testEmail, new User());
+ var roleAddToUser = userManager.GetRoleAddToUser(testEmail, new User());
- _dbContext.Remove(beforeItem);
- await _dbContext.SaveChangesAsync();
+ _dbContext.Remove(beforeItem);
+ await _dbContext.SaveChangesAsync();
- Assert.IsNotNull(roleAddToUser);
- Assert.AreEqual("Administrator", roleAddToUser);
- }
+ Assert.IsNotNull(roleAddToUser);
+ Assert.AreEqual("Administrator", roleAddToUser);
+ }
- [TestMethod]
- public async Task UserManager_GetRoleAddToUser_User()
- {
- var beforeItem = new User() { Name = "27898349abc9487" };
- await _dbContext.Users.AddAsync(beforeItem);
- await _dbContext.SaveChangesAsync();
+ [TestMethod]
+ public async Task UserManager_GetRoleAddToUser_User()
+ {
+ var beforeItem = new User() { Name = "27898349abc9487" };
+ await _dbContext.Users.AddAsync(beforeItem);
+ await _dbContext.SaveChangesAsync();
- const string testEmail = "dont2@mail.me";
- var userManager = new UserManager(_dbContext, new AppSettings
- {
- AddMemoryCache = false,
- AccountRegisterFirstRoleAdmin = false,
- AccountRegisterDefaultRole = AccountRoles.AppAccountRoles.Administrator,
+ const string testEmail = "dont2@mail.me";
+ var userManager = new UserManager(_dbContext, new AppSettings
+ {
+ AddMemoryCache = false,
+ AccountRegisterFirstRoleAdmin = false,
+ AccountRegisterDefaultRole = AccountRoles.AppAccountRoles.Administrator,
#pragma warning disable CS8670 // Object or collection initializer implicitly dereferences possibly null member.
- AccountRolesByEmailRegisterOverwrite = { { testEmail, "User" } }
+ AccountRolesByEmailRegisterOverwrite = { { testEmail, "User" } }
#pragma warning restore CS8670 // Object or collection initializer implicitly dereferences possibly null member.
- }, new FakeIWebLogger(), _memoryCache);
+ }, new FakeIWebLogger(), _memoryCache);
- var roleAddToUser = userManager.GetRoleAddToUser(testEmail, new User());
+ var roleAddToUser = userManager.GetRoleAddToUser(testEmail, new User());
- _dbContext.Remove(beforeItem);
- await _dbContext.SaveChangesAsync();
+ _dbContext.Remove(beforeItem);
+ await _dbContext.SaveChangesAsync();
- Assert.IsNotNull(roleAddToUser);
- Assert.AreEqual("User", roleAddToUser);
- }
+ Assert.IsNotNull(roleAddToUser);
+ Assert.AreEqual("User", roleAddToUser);
+ }
- [TestMethod]
- public async Task UserManager_GetRoleAddToUser_BogusRole()
- {
- var beforeItem = new User() { Name = "27898349abc9487" };
- await _dbContext.Users.AddAsync(beforeItem);
- await _dbContext.SaveChangesAsync();
+ [TestMethod]
+ public async Task UserManager_GetRoleAddToUser_BogusRole()
+ {
+ var beforeItem = new User() { Name = "27898349abc9487" };
+ await _dbContext.Users.AddAsync(beforeItem);
+ await _dbContext.SaveChangesAsync();
- const string testEmail = "dont2@mail.me";
- var userManager = new UserManager(_dbContext, new AppSettings
- {
- AddMemoryCache = false,
- AccountRegisterFirstRoleAdmin = false,
- AccountRegisterDefaultRole = AccountRoles.AppAccountRoles.User,
+ const string testEmail = "dont2@mail.me";
+ var userManager = new UserManager(_dbContext, new AppSettings
+ {
+ AddMemoryCache = false,
+ AccountRegisterFirstRoleAdmin = false,
+ AccountRegisterDefaultRole = AccountRoles.AppAccountRoles.User,
#pragma warning disable CS8670 // Object or collection initializer implicitly dereferences possibly null member.
- AccountRolesByEmailRegisterOverwrite = { { testEmail, "BogusRole" } }
+ AccountRolesByEmailRegisterOverwrite = { { testEmail, "BogusRole" } }
#pragma warning restore CS8670 // Object or collection initializer implicitly dereferences possibly null member.
- }, new FakeIWebLogger(), _memoryCache);
+ }, new FakeIWebLogger(), _memoryCache);
- var roleAddToUser = userManager.GetRoleAddToUser(testEmail, new User());
+ var roleAddToUser = userManager.GetRoleAddToUser(testEmail, new User());
- _dbContext.Remove(beforeItem);
- await _dbContext.SaveChangesAsync();
+ _dbContext.Remove(beforeItem);
+ await _dbContext.SaveChangesAsync();
- Assert.IsNotNull(roleAddToUser);
- // does fallback to default role
- Assert.AreEqual("User", roleAddToUser);
- }
+ Assert.IsNotNull(roleAddToUser);
+ // does fallback to default role
+ Assert.AreEqual("User", roleAddToUser);
+ }
- [TestMethod]
- public async Task UserManager_GetRoleAddToUser_IgnoreItself()
- {
- const string testEmail = "dont3@mail.me";
- const string id = "4859353904354";
+ [TestMethod]
+ public async Task UserManager_GetRoleAddToUser_IgnoreItself()
+ {
+ const string testEmail = "dont3@mail.me";
+ const string id = "4859353904354";
- foreach ( var user in await _dbContext.Users.ToListAsync() )
- {
- _dbContext.Users.Remove(user);
- }
+ foreach ( var user in await _dbContext.Users.ToListAsync() )
+ {
+ _dbContext.Users.Remove(user);
+ }
- await _dbContext.SaveChangesAsync();
+ await _dbContext.SaveChangesAsync();
- await _dbContext.Users.AddAsync(new User() { Name = id });
- await _dbContext.SaveChangesAsync();
- var beforeItem =
- _dbContext.Users.FirstOrDefault(p => p.Name == id);
+ await _dbContext.Users.AddAsync(new User() { Name = id });
+ await _dbContext.SaveChangesAsync();
+ var beforeItem =
+ await _dbContext.Users.FirstOrDefaultAsync(p => p.Name == id);
- Assert.IsNotNull(beforeItem);
- Assert.AreEqual(id, _dbContext.Users.FirstOrDefault(p => p.Name == id)?.Name);
+ Assert.IsNotNull(beforeItem);
+ Assert.AreEqual(id, (await _dbContext.Users.FirstOrDefaultAsync(p => p.Name == id))?.Name);
- var userManager = new UserManager(_dbContext,
- new AppSettings
- {
- AddMemoryCache = false,
- AccountRegisterFirstRoleAdmin = true,
- AccountRegisterDefaultRole = AccountRoles.AppAccountRoles.User,
- }, new FakeIWebLogger(), _memoryCache);
+ var userManager = new UserManager(_dbContext,
+ new AppSettings
+ {
+ AddMemoryCache = false,
+ AccountRegisterFirstRoleAdmin = true,
+ AccountRegisterDefaultRole = AccountRoles.AppAccountRoles.User,
+ }, new FakeIWebLogger(), _memoryCache);
- var roleAddToUser = userManager.GetRoleAddToUser(testEmail, beforeItem);
+ var roleAddToUser = userManager.GetRoleAddToUser(testEmail, beforeItem);
- // clean user
- _dbContext.Users.Remove(_dbContext.Users.FirstOrDefault(p => p.Name == id)!);
- await _dbContext.SaveChangesAsync();
+ // clean user
+ var item = await _dbContext.Users.FirstOrDefaultAsync(p => p.Name == id);
+ _dbContext.Users.Remove(item!);
+ await _dbContext.SaveChangesAsync();
- // check right roles
- Assert.AreEqual("Administrator", roleAddToUser);
- }
+ // check right roles
+ Assert.AreEqual("Administrator", roleAddToUser);
}
}
diff --git a/starsky/starskytest/starsky.foundation.platform/Middleware/NoAccountMiddlewareTest.cs b/starsky/starskytest/starsky.foundation.platform/Middleware/NoAccountMiddlewareTest.cs
index c8a7d71407..1a9056e006 100644
--- a/starsky/starskytest/starsky.foundation.platform/Middleware/NoAccountMiddlewareTest.cs
+++ b/starsky/starskytest/starsky.foundation.platform/Middleware/NoAccountMiddlewareTest.cs
@@ -1,3 +1,4 @@
+using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
@@ -8,249 +9,334 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using starsky.foundation.accountmanagement.Interfaces;
using starsky.foundation.accountmanagement.Middleware;
+using starsky.foundation.accountmanagement.Models;
using starsky.foundation.accountmanagement.Services;
using starsky.foundation.database.Data;
+using starsky.foundation.database.Models.Account;
using starsky.foundation.platform.Interfaces;
+using starsky.foundation.platform.JsonConverter;
using starsky.foundation.platform.Models;
using starskytest.FakeMocks;
-namespace starskytest.starsky.foundation.platform.Middleware
+namespace starskytest.starsky.foundation.platform.Middleware;
+
+[TestClass]
+public sealed class NoAccountMiddlewareTest
{
- [TestClass]
- public sealed class NoAccountMiddlewareTest
+ private readonly ServiceProvider _serviceProvider;
+
+ public NoAccountMiddlewareTest()
{
- private readonly ServiceProvider _serviceProvider;
+ var services = new ServiceCollection();
+ // IHttpContextAccessor is required for SignInManager, and UserManager
+
+ var builder = new DbContextOptionsBuilder();
+ builder.UseInMemoryDatabase("test");
+ var options = builder.Options;
+ var context = new ApplicationDbContext(options);
+ services.AddSingleton(context);
+
+ services.AddSingleton();
+
+ services.AddSingleton();
+ services.AddSingleton();
+
- public NoAccountMiddlewareTest()
+ services
+ .AddAuthentication(sharedOptions =>
+ {
+ sharedOptions.DefaultAuthenticateScheme =
+ CookieAuthenticationDefaults.AuthenticationScheme;
+ sharedOptions.DefaultSignInScheme =
+ CookieAuthenticationDefaults.AuthenticationScheme;
+ sharedOptions.DefaultChallengeScheme =
+ CookieAuthenticationDefaults.AuthenticationScheme;
+ }).AddCookie();
+
+ services.AddLogging();
+
+ _serviceProvider = services.BuildServiceProvider();
+
+ var httpContext = new DefaultHttpContext
{
- var services = new ServiceCollection();
- // IHttpContextAccessor is required for SignInManager, and UserManager
-
- var builder = new DbContextOptionsBuilder();
- builder.UseInMemoryDatabase("test");
- var options = builder.Options;
- var context = new ApplicationDbContext(options);
- services.AddSingleton(context);
-
- services.AddSingleton();
-
- services.AddSingleton();
- services.AddSingleton();
-
-
- services
- .AddAuthentication(sharedOptions =>
- {
- sharedOptions.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
- sharedOptions.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
- sharedOptions.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
- }).AddCookie();
+ Request = { Path = "/" },
+ RequestServices = _serviceProvider,
+ Connection =
+ {
+ RemoteIpAddress = IPAddress.Loopback, LocalIpAddress = IPAddress.Loopback
+ }
+ };
- services.AddLogging();
-
- _serviceProvider = services.BuildServiceProvider();
+ services.AddSingleton(
+ new HttpContextAccessor { HttpContext = httpContext });
+ // and rebuild
+ _serviceProvider = services.BuildServiceProvider();
+ }
+
+ [TestMethod]
+ public async Task OnHomePageNotLoginShouldAutoLogin()
+ {
+ var invoked = false;
+ var middleware = new NoAccountMiddleware(_ =>
+ {
+ invoked = true;
+ return Task.CompletedTask;
+ }, new AppSettings());
+
+ var services = new ServiceCollection();
+ services.AddSingleton();
+ var serviceProvider = services.BuildServiceProvider();
- var httpContext = new DefaultHttpContext
+ var httpContext = new DefaultHttpContext
+ {
+ Request = { Path = "/" },
+ Connection =
{
- Request = { Path = "/"},
- RequestServices = _serviceProvider,
- Connection = { RemoteIpAddress = IPAddress.Loopback, LocalIpAddress = IPAddress.Loopback}
- };
-
- services.AddSingleton(
- new HttpContextAccessor()
- {
- HttpContext = httpContext,
- });
- // and rebuild
- _serviceProvider = services.BuildServiceProvider();
- }
-
- [TestMethod]
- public async Task OnHomePageNotLoginShouldAutoLogin()
+ RemoteIpAddress = IPAddress.Loopback, LocalIpAddress = IPAddress.Loopback
+ },
+ RequestServices = serviceProvider
+ };
+ await middleware.Invoke(httpContext);
+
+ var userManager = serviceProvider.GetService() as FakeUserManagerActiveUsers;
+
+ Assert.IsTrue(userManager?.Users.Exists(p =>
+ p.Credentials!.Any(
+ credential => credential.Identifier == NoAccountMiddleware.Identifier)));
+
+ Assert.IsTrue(invoked);
+ }
+
+ [TestMethod]
+ public async Task OnHomePageNotLoginShouldAutoLogin_DemoModeOn()
+ {
+ var invoked = false;
+ var middleware = new NoAccountMiddleware(_ =>
{
- var invoked = false;
- var middleware = new NoAccountMiddleware(next:
- (_) =>
- {
- invoked = true;
- return Task.CompletedTask;
- }, new AppSettings());
-
- var services = new ServiceCollection();
- services.AddSingleton();
- var serviceProvider = services.BuildServiceProvider();
-
- var httpContext = new DefaultHttpContext
+ invoked = true;
+ return Task.CompletedTask;
+ }, new AppSettings { DemoUnsafeDeleteStorageFolder = true });
+
+ var services = new ServiceCollection();
+ services.AddSingleton();
+ var serviceProvider = services.BuildServiceProvider();
+
+ var httpContext = new DefaultHttpContext
+ {
+ Request = { Path = "/" },
+ RequestServices = serviceProvider,
+ Connection =
{
- Request =
- {
- Path = "/"
- },
- Connection = { RemoteIpAddress = IPAddress.Loopback, LocalIpAddress = IPAddress.Loopback},
- RequestServices = serviceProvider
- };
- await middleware.Invoke(httpContext);
-
- var userManager = serviceProvider.GetService() as FakeUserManagerActiveUsers;
-
- Assert.IsTrue(userManager?.Users.Exists(p => p.Credentials!.Any(credential => credential.Identifier == NoAccountMiddleware.Identifier)));
-
- Assert.IsTrue(invoked);
- }
-
- [TestMethod]
- public async Task OnHomePageNotLoginShouldAutoLogin_DemoModeOn()
+ RemoteIpAddress = IPAddress.Parse("1.0.0.1"),
+ LocalIpAddress = IPAddress.Loopback
+ }
+ };
+ await middleware.Invoke(httpContext);
+
+ var userManager = serviceProvider.GetService() as FakeUserManagerActiveUsers;
+ Assert.IsTrue(userManager?.Users.Exists(p =>
+ p.Credentials?.Any(
+ credential => credential.Identifier == NoAccountMiddleware.Identifier) == true));
+
+ Assert.IsTrue(invoked);
+ }
+
+ [TestMethod]
+ public async Task OnApiPageNotLoginShouldIgnore()
+ {
+ var invoked = false;
+ var middleware = new NoAccountMiddleware(_ =>
{
- var invoked = false;
- var middleware = new NoAccountMiddleware(next:
- (_) =>
- {
- invoked = true;
- return Task.CompletedTask;
- }, new AppSettings{DemoUnsafeDeleteStorageFolder = true});
-
- var services = new ServiceCollection();
- services.AddSingleton();
- var serviceProvider = services.BuildServiceProvider();
-
- var httpContext = new DefaultHttpContext
+ invoked = true;
+ return Task.CompletedTask;
+ }, new AppSettings());
+
+ var services = new ServiceCollection();
+ services.AddSingleton();
+ var serviceProvider = services.BuildServiceProvider();
+
+ var httpContext = new DefaultHttpContext
+ {
+ Request = { Path = "/api/any" },
+ Connection =
{
- Request =
- {
- Path = "/"
- },
- RequestServices = serviceProvider,
- Connection = { RemoteIpAddress = IPAddress.Parse("1.0.0.1"), LocalIpAddress = IPAddress.Loopback},
- };
- await middleware.Invoke(httpContext);
-
- var userManager = serviceProvider.GetService() as FakeUserManagerActiveUsers;
- Assert.IsTrue(userManager?.Users.Exists(p => p.Credentials?.Any(credential => credential.Identifier == NoAccountMiddleware.Identifier) == true));
-
- Assert.IsTrue(invoked);
- }
-
- [TestMethod]
- public async Task OnApiPageNotLoginShouldIgnore()
+ RemoteIpAddress = IPAddress.Loopback, LocalIpAddress = IPAddress.Loopback
+ },
+ RequestServices = serviceProvider
+ };
+ await middleware.Invoke(httpContext);
+
+ var userManager = serviceProvider.GetService() as FakeUserManagerActiveUsers;
+ Assert.IsFalse(userManager?.Users.Exists(p =>
+ p.Credentials?.Any(
+ credential => credential.Identifier == NoAccountMiddleware.Identifier) == true));
+
+ Assert.IsTrue(invoked);
+ }
+
+ [TestMethod]
+ public async Task NullNotLoginShouldCreate()
+ {
+ var invoked = false;
+ var middleware = new NoAccountMiddleware(_ =>
{
- var invoked = false;
- var middleware = new NoAccountMiddleware(next:
- (_) =>
- {
- invoked = true;
- return Task.CompletedTask;
- },new AppSettings());
-
- var services = new ServiceCollection();
- services.AddSingleton();
- var serviceProvider = services.BuildServiceProvider();
-
- var httpContext = new DefaultHttpContext
+ invoked = true;
+ return Task.CompletedTask;
+ }, new AppSettings());
+
+ var services = new ServiceCollection();
+ services.AddSingleton();
+ var serviceProvider = services.BuildServiceProvider();
+
+ var httpContext = new DefaultHttpContext
+ {
+ Connection =
{
- Request =
- {
- Path = "/api/any"
- },
- Connection = { RemoteIpAddress = IPAddress.Loopback, LocalIpAddress = IPAddress.Loopback},
- RequestServices = serviceProvider
- };
- await middleware.Invoke(httpContext);
-
- var userManager = serviceProvider.GetService() as FakeUserManagerActiveUsers;
- Assert.IsFalse(userManager?.Users.Exists(p => p.Credentials?.Any(credential => credential.Identifier == NoAccountMiddleware.Identifier) == true));
-
- Assert.IsTrue(invoked);
- }
-
- [TestMethod]
- public async Task NullNotLoginShouldCreate()
+ RemoteIpAddress = IPAddress.Loopback, LocalIpAddress = IPAddress.Loopback
+ },
+ RequestServices = serviceProvider
+ // Missing Path
+ };
+
+ await middleware.Invoke(httpContext);
+
+ var userManager = serviceProvider.GetService() as FakeUserManagerActiveUsers;
+
+ Assert.IsTrue(userManager?.Users.Exists(p =>
+ p.Credentials?.Any(
+ credential => credential.Identifier == NoAccountMiddleware.Identifier) == true));
+
+ Assert.IsTrue(invoked);
+ }
+
+ [TestMethod]
+ public async Task HasClaim_AndAuthenticated()
+ {
+ var invoked = false;
+ var middleware = new NoAccountMiddleware(_ =>
{
- var invoked = false;
- var middleware = new NoAccountMiddleware(next:
- (_) =>
- {
- invoked = true;
- return Task.CompletedTask;
- }, new AppSettings());
-
- var services = new ServiceCollection();
- services.AddSingleton();
- var serviceProvider = services.BuildServiceProvider();
-
- var httpContext = new DefaultHttpContext
+ invoked = true;
+ return Task.CompletedTask;
+ }, new AppSettings());
+
+ var httpContextAccessor = _serviceProvider.GetRequiredService();
+ var userManager = _serviceProvider.GetRequiredService();
+
+ var result =
+ await userManager.SignUpAsync("test", "email", NoAccountMiddleware.Identifier, "test");
+
+ await userManager.SignIn(httpContextAccessor.HttpContext!, result.User);
+
+ await middleware.Invoke(httpContextAccessor.HttpContext!);
+
+ Assert.IsTrue(invoked);
+ Assert.IsTrue(httpContextAccessor.HttpContext?.User.Identity?.IsAuthenticated);
+ }
+
+ [TestMethod]
+ public async Task OnHomePageNotLoginShouldIgnoreDueOffNetwork()
+ {
+ var invoked = false;
+ var middleware = new NoAccountMiddleware(_ =>
+ {
+ invoked = true;
+ return Task.CompletedTask;
+ }, new AppSettings());
+
+ var services = new ServiceCollection();
+ services.AddSingleton();
+ var serviceProvider = services.BuildServiceProvider();
+
+ var httpContext = new DefaultHttpContext
+ {
+ Request = { Path = "/" },
+ Connection =
{
- Connection = { RemoteIpAddress = IPAddress.Loopback, LocalIpAddress = IPAddress.Loopback},
- RequestServices = serviceProvider
- // Missing Path
- };
-
- await middleware.Invoke(httpContext);
-
- var userManager = serviceProvider.GetService() as FakeUserManagerActiveUsers;
-
- Assert.IsTrue(userManager?.Users.Exists(p => p.Credentials?.Any(credential => credential.Identifier == NoAccountMiddleware.Identifier) == true));
-
- Assert.IsTrue(invoked);
- }
-
- [TestMethod]
- public async Task HasClaim_AndAuthenticated()
+ RemoteIpAddress = IPAddress.Parse("8.8.8.8"),
+ LocalIpAddress = IPAddress.Loopback
+ },
+ RequestServices = serviceProvider
+ };
+ await middleware.Invoke(httpContext);
+
+ var userManager = serviceProvider.GetService() as FakeUserManagerActiveUsers;
+ // false due off network
+ Assert.IsFalse(userManager!.Users.Exists(p =>
+ p.Credentials!.Any(
+ credential => credential.Identifier == NoAccountMiddleware.Identifier)));
+
+ Assert.IsTrue(invoked);
+ }
+
+ [TestMethod]
+ public async Task CreateOrUpdateNewUsers_NewUser()
+ {
+ var services = new ServiceCollection();
+ services.AddSingleton();
+ var serviceProvider = services.BuildServiceProvider();
+
+ var userManager = serviceProvider.GetRequiredService();
+
+ await NoAccountMiddleware.CreateOrUpdateNewUsers(userManager);
+
+ var test = userManager.GetUser("email", NoAccountMiddleware.Identifier);
+
+ Assert.IsNotNull(test);
+ Assert.AreEqual(NoAccountMiddleware.Identifier, test.Credentials!.First().Identifier);
+ Assert.AreEqual(IterationCountType.Iterate100KSha256,
+ test.Credentials!.First().IterationCount);
+ }
+
+ [DataTestMethod] // [Theory]
+ [DataRow(IterationCountType.IterateLegacySha1)]
+ [DataRow(IterationCountType.Iterate100KSha256)]
+ public async Task CreateOrUpdateNewUsers_UpgradeUser(IterationCountType iterationCountType)
+ {
+ var userManager = new FakeIUserManger(new UserOverviewModel
{
- var invoked = false;
- var middleware = new NoAccountMiddleware(next:
- (_) =>
+ Users =
+ [
+ new User
{
- invoked = true;
- return Task.CompletedTask;
- },new AppSettings());
-
- var httpContextAccessor = _serviceProvider.GetRequiredService();
- var userManager = _serviceProvider.GetRequiredService();
-
- var result = await userManager.SignUpAsync("test", "email", NoAccountMiddleware.Identifier, "test");
-
- await userManager.SignIn(httpContextAccessor.HttpContext!, result.User);
-
- await middleware.Invoke(httpContextAccessor.HttpContext!);
-
- Assert.IsTrue(invoked);
- Assert.IsTrue(httpContextAccessor.HttpContext?.User.Identity?.IsAuthenticated);
+ Credentials = new List
+ {
+ new()
+ {
+ Identifier = NoAccountMiddleware.Identifier,
+ CredentialType = new CredentialType { Code = "email" },
+ CredentialTypeId = 0,
+ IterationCount = iterationCountType,
+ Secret = "",
+ Extra = "",
+ Id = 0
+ }
+ }
+ }
+ ]
+ });
+ var beforeCredential = userManager.GetCredentialsByUserId(0).CloneViaJson();
+
+ await userManager.SignUpAsync(string.Empty, "email", NoAccountMiddleware.Identifier,
+ "test");
+
+ await NoAccountMiddleware.CreateOrUpdateNewUsers(userManager);
+
+ var test = userManager.GetUser("email", NoAccountMiddleware.Identifier);
+ Assert.IsNotNull(test);
+ Assert.AreEqual(NoAccountMiddleware.Identifier, test.Credentials!.First().Identifier);
+ Assert.AreEqual(IterationCountType.Iterate100KSha256,
+ test.Credentials!.First().IterationCount);
+
+ if ( iterationCountType == IterationCountType.Iterate100KSha256 )
+ {
+ Assert.AreEqual(beforeCredential?.Secret,
+ test.Credentials!.FirstOrDefault()!.Secret);
}
-
- [TestMethod]
- public async Task OnHomePageNotLoginShouldIgnoreDueOffNetwork()
+ else
{
- var invoked = false;
- var middleware = new NoAccountMiddleware(next:
- (_) =>
- {
- invoked = true;
- return Task.CompletedTask;
- },new AppSettings());
-
- var services = new ServiceCollection();
- services.AddSingleton();
- var serviceProvider = services.BuildServiceProvider();
-
- var httpContext = new DefaultHttpContext
- {
- Request =
- {
- Path = "/"
- },
- Connection = { RemoteIpAddress = IPAddress.Parse("8.8.8.8"), LocalIpAddress = IPAddress.Loopback},
- RequestServices = serviceProvider
- };
- await middleware.Invoke(httpContext);
-
- var userManager = serviceProvider.GetService() as FakeUserManagerActiveUsers;
- // false due off network
- Assert.IsFalse(userManager!.Users.Exists(p => p.Credentials!.Any(credential => credential.Identifier == NoAccountMiddleware.Identifier)));
-
- Assert.IsTrue(invoked);
+ Assert.AreNotEqual(beforeCredential?.Secret,
+ test.Credentials!.FirstOrDefault()!.Secret);
}
-
}
}
diff --git a/starsky/starskytest/starskyAdminCli/Services/ConsoleAdminTest.cs b/starsky/starskytest/starskyAdminCli/Services/ConsoleAdminTest.cs
index 939361a814..c50151b71a 100644
--- a/starsky/starskytest/starskyAdminCli/Services/ConsoleAdminTest.cs
+++ b/starsky/starskytest/starskyAdminCli/Services/ConsoleAdminTest.cs
@@ -7,125 +7,137 @@
using starskyAdminCli.Services;
using starskytest.FakeMocks;
-namespace starskytest.starskyAdminCli.Services
+namespace starskytest.starskyAdminCli.Services;
+
+[TestClass]
+public sealed class ConsoleAdminTest
{
- [TestClass]
- public sealed class ConsoleAdminTest
+ [TestMethod]
+ public async Task StarskyAdminCliProgramTest_UserDoesNotExist_AndCreateAccount()
{
- [TestMethod]
- public async Task StarskyAdminCliProgramTest_UserDoesNotExist_AndCreateAccount()
- {
- var console = new FakeConsoleWrapper(new List
- {
- "dont@mail.me", "1234567890123456"
- });
-
- var service = new ConsoleAdmin(new FakeUserManagerActiveUsers(), console);
- await service.Tool(string.Empty,
- string.Empty);
+ var console =
+ new FakeConsoleWrapper(new List { "dont@mail.me", "1234567890123456" });
- Assert.AreEqual("User dont@mail.me is created",
- console.WrittenLines.LastOrDefault());
- }
+ var service = new ConsoleAdmin(new FakeUserManagerActiveUsers(), console);
+ await service.Tool(string.Empty,
+ string.Empty);
- [TestMethod]
- public async Task CreateAccount_AsInput()
- {
- var console = new FakeConsoleWrapper();
- var service = new ConsoleAdmin(new FakeUserManagerActiveUsers(), console);
- await service.Tool("dont@mail.me", "1234567890123456");
+ Assert.AreEqual("User dont@mail.me is created",
+ console.WrittenLines.LastOrDefault());
+ }
- Assert.AreEqual("User dont@mail.me is created",
- console.WrittenLines.LastOrDefault());
- }
+ [TestMethod]
+ public async Task CreateAccount_AsInput()
+ {
+ var console = new FakeConsoleWrapper();
+ var service = new ConsoleAdmin(new FakeUserManagerActiveUsers(), console);
+ await service.Tool("dont@mail.me", "1234567890123456");
- [TestMethod]
- public async Task UserCreate_ValidationShouldFail()
- {
- var console = new FakeConsoleWrapper(new List { "no_email", "false" });
+ Assert.AreEqual("User dont@mail.me is created",
+ console.WrittenLines.LastOrDefault());
+ }
- var service = new ConsoleAdmin(new FakeUserManagerActiveUsers(), console);
- await service.Tool(string.Empty, string.Empty);
+ [TestMethod]
+ public async Task UserCreate_ValidationShouldFail()
+ {
+ var console = new FakeConsoleWrapper(new List { "no_email", "false" });
- Assert.AreEqual("username / password is not valid",
- console.WrittenLines.LastOrDefault());
- }
+ var service = new ConsoleAdmin(new FakeUserManagerActiveUsers(), console);
+ await service.Tool(string.Empty, string.Empty);
- [TestMethod]
- public async Task UserCreate_NoInput()
- {
- var console = new FakeConsoleWrapper(new List { "dont@mail.me", string.Empty });
+ Assert.AreEqual("username / password is not valid",
+ console.WrittenLines.LastOrDefault());
+ }
- var service = new ConsoleAdmin(new FakeUserManagerActiveUsers(), console);
- await service.Tool(string.Empty, string.Empty);
+ [TestMethod]
+ public async Task UserCreate_NoInput()
+ {
+ var console = new FakeConsoleWrapper(new List { "dont@mail.me", string.Empty });
- Assert.AreEqual("No input selected",
- console.WrittenLines.LastOrDefault());
- }
+ var service = new ConsoleAdmin(new FakeUserManagerActiveUsers(), console);
+ await service.Tool(string.Empty, string.Empty);
- [TestMethod]
- public async Task StarskyAdminCliProgramTest_NoInput()
- {
- var console = new FakeConsoleWrapper(new List { string.Empty });
- await new ConsoleAdmin(new FakeUserManagerActiveUsers(), console).Tool(string.Empty,
- string.Empty);
+ Assert.AreEqual("No input selected",
+ console.WrittenLines.LastOrDefault());
+ }
- Assert.AreEqual("No input selected",
- console.WrittenLines.LastOrDefault());
- }
+ [TestMethod]
+ public async Task StarskyAdminCliProgramTest_NoInput()
+ {
+ var console = new FakeConsoleWrapper(new List { string.Empty });
+ await new ConsoleAdmin(new FakeUserManagerActiveUsers(), console).Tool(string.Empty,
+ string.Empty);
- [TestMethod]
- public async Task StarskyAdminCliProgramTest_Removed()
- {
- var console = new FakeConsoleWrapper(new List { "test", "2" });
- await new ConsoleAdmin(
- new FakeUserManagerActiveUsers("test", new User { Name = "t1", Id = 99 }),
- console)
- .Tool(string.Empty, string.Empty);
-
- Assert.AreEqual("User test is removed",
- console.WrittenLines.LastOrDefault());
- }
-
- [TestMethod]
- public async Task ToggleUserAdminRole_toAdmin()
- {
- var console = new FakeConsoleWrapper(new List { "test", "3" });
- await new ConsoleAdmin(
- new FakeUserManagerActiveUsers("test", new User { Name = "t1", Id = 99 }), console
- ).Tool(string.Empty, string.Empty);
+ Assert.AreEqual("No input selected",
+ console.WrittenLines.LastOrDefault());
+ }
- Assert.AreEqual("User test has now the role Administrator",
- console.WrittenLines.LastOrDefault());
- }
+ [TestMethod]
+ public async Task StarskyAdminCliProgramTest_Removed()
+ {
+ var console = new FakeConsoleWrapper(new List { "test", "2" });
+ await new ConsoleAdmin(
+ new FakeUserManagerActiveUsers("test", new User { Name = "t1", Id = 99 }),
+ console)
+ .Tool(string.Empty, string.Empty);
+
+ Assert.AreEqual("User test is removed",
+ console.WrittenLines.LastOrDefault());
+ }
- [TestMethod]
- public async Task ToggleUserAdminRole_toUser()
- {
- var console = new FakeConsoleWrapper(new List { "test", "3" });
+ [TestMethod]
+ public async Task ToggleUserAdminRole_toAdmin()
+ {
+ var console = new FakeConsoleWrapper(new List