using Microsoft.AspNetCore.Identity;
using NTDLS.Helpers;
using System.Security.Claims;
using TightWiki.Library;
namespace TightWiki.Repository
{
public static class SecurityRepository
{
///
/// Detect whether this is the first time the WIKI has ever been run and do some initialization.
/// Adds the first user with the email and password contained in Constants.DEFAULTUSERNAME and Constants.DEFAULTPASSWORD
///
public static async void ValidateEncryptionAndCreateAdminUser(UserManager userManager)
{
if (ConfigurationRepository.IsFirstRun())
{
//If this is the first time the app has run on this machine (based on an encryption key) then clear the admin password status.
//This will cause the application to set the admin password to the default password and display a warning until it is changed.
UsersRepository.SetAdminPasswordClear();
}
if (UsersRepository.AdminPasswordStatus() == Constants.AdminPasswordChangeState.NeedsToBeSet)
{
var user = await userManager.FindByNameAsync(Constants.DEFAULTUSERNAME);
if (user == null)
{
var creationResult = await userManager.CreateAsync(new IdentityUser(Constants.DEFAULTUSERNAME), Constants.DEFAULTPASSWORD);
if (!creationResult.Succeeded)
{
throw new Exception(string.Join("\r\n", creationResult.Errors.Select(o => o.Description)));
}
user = await userManager.FindByNameAsync(Constants.DEFAULTUSERNAME);
}
user.EnsureNotNull();
user.Email = Constants.DEFAULTUSERNAME; // Ensure email is set or updated
user.EmailConfirmed = true;
var emailUpdateResult = await userManager.UpdateAsync(user);
if (!emailUpdateResult.Succeeded)
{
throw new Exception(string.Join("\r\n", emailUpdateResult.Errors.Select(o => o.Description)));
}
var membershipConfig = ConfigurationRepository.GetConfigurationEntryValuesByGroupName("Membership");
var claimsToAdd = new List
{
new (ClaimTypes.Role, "Administrator"),
new ("timezone", membershipConfig.Value("Default TimeZone").EnsureNotNull()),
new (ClaimTypes.Country, membershipConfig.Value("Default Country").EnsureNotNull()),
new ("language", membershipConfig.Value("Default Language").EnsureNotNull()),
};
UpsertUserClaims(userManager, user, claimsToAdd);
var token = await userManager.GeneratePasswordResetTokenAsync(user.EnsureNotNull());
var result = await userManager.ResetPasswordAsync(user, token, Constants.DEFAULTPASSWORD);
if (!result.Succeeded)
{
throw new Exception(string.Join("\r\n", emailUpdateResult.Errors.Select(o => o.Description)));
}
UsersRepository.SetAdminPasswordIsDefault();
var existingProfileUserId = UsersRepository.GetUserAccountIdByNavigation(Navigation.Clean(Constants.DEFAULTACCOUNT));
if (existingProfileUserId == null)
{
UsersRepository.CreateProfile(Guid.Parse(user.Id), Constants.DEFAULTACCOUNT);
}
else
{
UsersRepository.SetProfileUserId(Constants.DEFAULTACCOUNT, Guid.Parse(user.Id));
}
}
}
public static async void UpsertUserClaims(UserManager userManager, IdentityUser user, List givenClaims)
{
// Get existing claims for the user
var existingClaims = await userManager.GetClaimsAsync(user);
foreach (var givenClaim in givenClaims)
{
// Remove existing claims if they exist
var firstNameClaim = existingClaims.FirstOrDefault(c => c.Type == givenClaim.Type);
if (firstNameClaim != null)
{
await userManager.RemoveClaimAsync(user, firstNameClaim);
}
// Add new claim.
await userManager.AddClaimAsync(user, givenClaim);
}
var result = await userManager.UpdateAsync(user);
if (!result.Succeeded)
{
throw new Exception(string.Join("
\r\n", result.Errors.Select(o => o.Description)));
}
}
}
}