Add project files.

This commit is contained in:
2023-04-29 09:17:17 +03:00
commit 62178f1f32
493 changed files with 45863 additions and 0 deletions
@@ -0,0 +1,34 @@
namespace MyOffice.Web.Identity.Configure;
using MyOffice.Web.Infrastructure;
using IdentityServer4.AccessTokenValidation;
using Microsoft.Extensions.Options;
public class ConfigureIdentityServerOptions : IConfigureNamedOptions<IdentityServerAuthenticationOptions>
{
readonly GlobalSettings _globalSettings;
readonly ILogger<ConfigureIdentityServerOptions> _logger;
public ConfigureIdentityServerOptions(
GlobalSettings globalSettings,
ILogger<ConfigureIdentityServerOptions> logger
)
{
_globalSettings = globalSettings;
_logger = logger;
}
public void Configure(string? name, IdentityServerAuthenticationOptions options)
{
//_logger.LogError($"Configure: {_globalSettings.Host}");
if (name == IdentityServerAuthenticationDefaults.AuthenticationScheme)
{
options.RequireHttpsMetadata = false;
options.ApiName = IdentityServerConfig.ApiName;
options.Authority = _globalSettings.Host;
}
}
// This won't be called, but is required for the IConfigureNamedOptions interface
public void Configure(IdentityServerAuthenticationOptions options) => Configure(Options.DefaultName, options);
}
@@ -0,0 +1,107 @@
namespace MyOffice.Web.Identity.Configure;
using IdentityModel;
using IdentityServer4;
using IdentityServer4.Models;
public class IdentityServerConfig
{
public static class ClaimConstants
{
public const string Subject = "subject";
public const string Permission = "permission";
}
public static class ScopeConstants
{
public const string Roles = "roles";
}
public const string ApiName = "api";
public const string ApiFriendlyName = "MyOffice.Web API";
public const string AppClientID = "angulartemplate_spa";
public static IEnumerable<IdentityResource> GetIdentityResources()
{
return new List<IdentityResource>
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
new IdentityResources.Phone(),
new IdentityResources.Email(),
new(ScopeConstants.Roles, new List<string> { JwtClaimTypes.Role })
};
}
public static IEnumerable<ApiScope> GetApiScopes()
{
return new List<ApiScope>
{
new(ApiName, ApiFriendlyName)
{
UserClaims =
{
JwtClaimTypes.Name,
JwtClaimTypes.Email,
JwtClaimTypes.PhoneNumber,
JwtClaimTypes.Role,
ClaimConstants.Permission
}
}
};
}
public static IEnumerable<ApiResource> GetApiResources()
{
return new List<ApiResource>
{
new(ApiName)
{
Scopes = { ApiName }
}
};
}
public static IEnumerable<Client> GetClients()
{
return new List<Client>
{
new()
{
ClientId = AppClientID,
ClientSecrets = new List<Secret>
{
new Secret("secret".Sha256())
},
AllowedGrantTypes = new[]
{
GrantType.AuthorizationCode,
GrantType.ClientCredentials,
GrantType.DeviceFlow,
GrantType.ResourceOwnerPassword,
"external"
},
AllowAccessTokensViaBrowser = true,
RequireClientSecret = false,
RedirectUris = new[]
{
"http://localhost:4200/silent-refresh.html",
},
AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Phone,
IdentityServerConstants.StandardScopes.Email,
ScopeConstants.Roles,
ApiName
},
AllowOfflineAccess = true,
RefreshTokenExpiration = TokenExpiration.Sliding,
RefreshTokenUsage = TokenUsage.OneTimeOnly
}
};
}
}
@@ -0,0 +1,27 @@
namespace MyOffice.Web.Identity;
using Core.Extensions;
using IdentityServer4.Services;
using Infrastructure;
public class CorsPolicyService : ICorsPolicyService
{
private readonly ILogger<CorsPolicyService> _logger;
private readonly GlobalSettings _globalSettings;
public CorsPolicyService(
ILogger<CorsPolicyService> logger,
GlobalSettings globalSettings
)
{
_logger = logger;
_globalSettings = globalSettings;
}
public Task<bool> IsOriginAllowedAsync(string origin)
{
var result = origin.EqualsIgnoreCase(_globalSettings.Host);
return Task.FromResult(result);
}
}
@@ -0,0 +1,5 @@
namespace MyOffice.Web.Identity.Domain;
public class ApplicationRole
{
}
@@ -0,0 +1,16 @@
namespace MyOffice.Web.Identity.Domain;
public class ApplicationUser<TKey>
{
#pragma warning disable CS8618 // Non-nullable property 'Id' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
public TKey Id { get; set; }
#pragma warning restore CS8618 // Non-nullable property 'Id' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
public string UserName { get; set; } = null!;
public string Email { get; set; } = null!;
public string PasswordHash { get; set; } = null!;
public string? FirstName { get; set; }
public string? LastName { get; set; }
public string? FullName { get; set; }
public bool IsEmailConfirmed { get; set; }
}
@@ -0,0 +1,19 @@
namespace MyOffice.Web.Identity.Domain;
public class ExternalProvidersConfig
{
public class Auth0Config
{
public string? ClientId { get; set; }
public string? Domain { get; set; }
public string? SecretKey { get; set; }
}
public class GoogleConfig
{
public string? ClientId { get; set; }
}
public Auth0Config? Auth0 { get; set; }
public GoogleConfig? Google { get; set; }
}
@@ -0,0 +1,167 @@
namespace MyOffice.Web.Identity;
using MyOffice.Data.Models.Users;
using Domain;
using Data.Repositories.Users;
using Repositories;
using IdentityModel;
using IdentityServer4.Models;
using IdentityServer4.Validation;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options;
using System.Security.Claims;
using Core.Extensions;
using Core.Identity;
public class ExtensionGrantValidator : IExtensionGrantValidator
{
private readonly IUserStore<ApplicationUser<Guid>> _userStore;
private readonly ILogger<ExtensionGrantValidator> _logger;
private readonly AppUserManager _appUserManager;
private readonly IUserExternalRepository _userExternalRepository;
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly ExternalProvidersConfig _externalProvidersConfig;
private readonly IEnumerable<IExternalProviderValidator> _externalProviderValidators;
public ExtensionGrantValidator(
ILogger<ExtensionGrantValidator> logger,
IUserStore<ApplicationUser<Guid>> userStore,
AppUserManager appUserManager,
IUserExternalRepository userExternalRepository,
IHttpContextAccessor httpContextAccessor,
IOptions<ExternalProvidersConfig> externalProvidersConfig,
IEnumerable<IExternalProviderValidator> externalProviderValidators
)
{
if (externalProvidersConfig == null)
throw new ArgumentNullException(nameof(externalProvidersConfig));
_userStore = userStore ?? throw new ArgumentNullException(nameof(userStore));
_appUserManager = appUserManager ?? throw new ArgumentNullException(nameof(appUserManager));
_userExternalRepository =
userExternalRepository ?? throw new ArgumentNullException(nameof(userExternalRepository));
_httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor));
_externalProvidersConfig = externalProvidersConfig.Value;
_externalProviderValidators = externalProviderValidators;
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public string GrantType => "external";
public async Task ValidateAsync(ExtensionGrantValidationContext context)
{
var provider = context.Request.Raw["provider"];
if (provider == null)
throw new ArgumentNullException("provider not found");
var validator = _externalProviderValidators.FirstOrDefault(x => x.Provider.EqualsIgnoreCase(provider));
if (validator == null || !validator.IsConfigured)
{
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidRequest,
$"Provider not supported: {provider}");
return;
}
var token = context.Request.Raw["token"];
if (token == null)
throw new ArgumentNullException("token not found");
var result = await validator.ValidateAsync(token);
if (!result.IsSuccessed)
{
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidRequest, $"Token not valid");
return;
}
context.Result = await ProcessAsync(result.Email!, result.ExternalId!, provider, result.EmailVerified,
result.FullName);
}
private readonly object _lock = new();
private async Task<GrantValidationResult> ProcessAsync(
string email,
string externlaId,
string provider,
bool isEmailConfirmed,
string? fullName
)
{
// connect to exists user
if (_httpContextAccessor.HttpContext?.User?.Identity?.IsAuthenticated == true)
{
return new GrantValidationResult(TokenRequestErrors.InvalidRequest, $"Authentication failed");
}
else
{
var user = await _appUserManager.FindByEmailAsync(email);
if (user == null)
{
if (!isEmailConfirmed)
return new GrantValidationResult(TokenRequestErrors.InvalidRequest, "Email not confirmed");
user = await CreateUser(email, isEmailConfirmed, fullName);
if (user == null) return new GrantValidationResult(TokenRequestErrors.InvalidRequest);
}
var claim = await _userExternalRepository.GetByUserIdAsync(user.Id, provider);
if (claim == null) claim = AddClaim(user, email, externlaId, provider);
return ClaimToGrantValidationResult(claim.UserId, "", "");
}
}
private async Task<ApplicationUser<Guid>?> CreateUser(string email, bool isEmailConfirmed, string? fullName)
{
var user = new ApplicationUser<Guid>
{
Id = Guid.NewGuid(),
UserName = email,
Email = email,
IsEmailConfirmed = isEmailConfirmed,
FullName = fullName
};
var password = "Qq1!_" + Guid.NewGuid();
var result = await _appUserManager.CreateAsync(user, password);
if (!result.Succeeded) return null;
return user;
}
private UserExternal AddClaim(ApplicationUser<Guid> user, string email, string externalId, string provider)
{
lock (_lock)
{
var claim = _userExternalRepository.GetByUserId(user.Id, provider);
if (claim != null) return claim;
claim = new UserExternal
{
UserId = user.Id,
CreatedOn = DateTime.UtcNow,
Provider = provider.ToLower(),
ExternalId = externalId,
Email = email
};
_userExternalRepository.AddUserExternal(claim);
return claim;
}
}
private GrantValidationResult ClaimToGrantValidationResult(Guid userId, string provider, string email)
{
var userIdStr = userId.ToString();
var claims = new List<Claim>
{
new(JwtClaimTypes.Id, userIdStr),
new(JwtClaimTypes.Subject, userIdStr),
new(JwtClaimTypes.Email, email)
};
var grantValidationResult = new GrantValidationResult(userIdStr, provider, claims);
return grantValidationResult;
}
}
@@ -0,0 +1,69 @@
namespace MyOffice.Web.Identity.ExternalProviders;
using Domain;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Protocols;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Text;
using Core.Extensions;
using Core.Identity;
public class ExternalProviderValidatorAuth0 : IExternalProviderValidator
{
private readonly ExternalProvidersConfig _externalProvidersConfig;
private readonly ILogger<ExternalProviderValidatorAuth0> _logger;
public ExternalProviderValidatorAuth0(
ILogger<ExternalProviderValidatorAuth0> logger,
IOptions<ExternalProvidersConfig> externalProvidersConfig
)
{
_externalProvidersConfig = externalProvidersConfig.Value;
_logger = logger;
Provider = ExternalProvidersConst.PROVIDER_AUTH0;
IsConfigured = _externalProvidersConfig.IsAuth0Configured();
}
public string Provider { get; }
public bool IsConfigured { get; }
public async Task<ExternalProviderValidatorResult> ValidateAsync(string token)
{
var auth0Domain = _externalProvidersConfig.Auth0!.Domain!;
var secretKey = _externalProvidersConfig.Auth0!.SecretKey!;
var securityKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(secretKey));
var configurationManager = new ConfigurationManager<OpenIdConnectConfiguration>(
$"{auth0Domain}.well-known/openid-configuration", new OpenIdConnectConfigurationRetriever());
var openIdConfig = await configurationManager.GetConfigurationAsync(CancellationToken.None);
var validations = new TokenValidationParameters
{
ValidIssuer = auth0Domain,
ValidAudiences = new[] { _externalProvidersConfig.Auth0!.ClientId },
IssuerSigningKeys = openIdConfig.SigningKeys,
TokenDecryptionKey = securityKey
};
var tokenHandler = new JwtSecurityTokenHandler();
var user = tokenHandler.ValidateToken(token, validations, out var validatedToken);
if (user.Identity?.IsAuthenticated != true)
{
return ExternalProviderValidatorResult.Failed();
}
var email = user.Claims.GetEmail();
var emailVerified = user.Claims.GetValue("email_verified").AsBool();
var fullName = user.Claims.GetValue("name")?.ToString();
var externalId = user.Claims.GetSID();
if (email == null || externalId == null)
{
return ExternalProviderValidatorResult.Failed();
}
return ExternalProviderValidatorResult.Success(email, emailVerified, externalId, fullName);
}
}
@@ -0,0 +1,36 @@
namespace MyOffice.Web.Identity.ExternalProviders;
using MyOffice.Core.Identity;
using Domain;
using Google.Apis.Auth;
using Microsoft.Extensions.Options;
public class ExternalProviderValidatorGoogle : IExternalProviderValidator
{
private readonly ExternalProvidersConfig _externalProvidersConfig;
public ExternalProviderValidatorGoogle(
IOptions<ExternalProvidersConfig> externalProvidersConfig
)
{
_externalProvidersConfig = externalProvidersConfig.Value;
Provider = ExternalProvidersConst.PROVIDER_GOOGLE;
IsConfigured = _externalProvidersConfig.IsGoogleConfigured();
}
public string Provider { get; }
public bool IsConfigured { get; }
public async Task<ExternalProviderValidatorResult> ValidateAsync(string token)
{
var settings = new GoogleJsonWebSignature.ValidationSettings()
{
Audience = new List<string>() { _externalProvidersConfig.Google!.ClientId! }
};
var result = await GoogleJsonWebSignature.ValidateAsync(token, settings);
if (!result.EmailVerified) return ExternalProviderValidatorResult.Failed();
return ExternalProviderValidatorResult.Success(result.Email, result.EmailVerified, result.Subject, result.Name);
}
}
@@ -0,0 +1,7 @@
namespace MyOffice.Web.Identity.ExternalProviders;
public class ExternalProvidersConst
{
public const string PROVIDER_GOOGLE = "google";
public const string PROVIDER_AUTH0 = "auth0";
}
@@ -0,0 +1,24 @@
using MyOffice.Web.Identity.Domain;
namespace MyOffice.Web.Identity;
using Core.Extensions;
public static class ExternalProvidersConfigExtensions
{
public static bool IsGoogleConfigured(this ExternalProvidersConfig? config)
{
return config != null
&& config.Google != null
&& config.Google.ClientId.IsPresent();
}
public static bool IsAuth0Configured(this ExternalProvidersConfig? config)
{
return config != null
&& config.Auth0 != null
&& config.Auth0.ClientId.IsPresent()
&& config.Auth0.Domain.IsPresent()
&& config.Auth0.SecretKey.IsPresent();
}
}
@@ -0,0 +1,54 @@
namespace MyOffice.Web.Identity;
using System.Collections.Concurrent;
using Core.Extensions;
using IdentityServer4.Models;
using IdentityServer4.Stores;
public class PersistedGrantStore : IPersistedGrantStore
{
private static ConcurrentDictionary<string, PersistedGrant> _store = new ConcurrentDictionary<string, PersistedGrant>();
public Task StoreAsync(PersistedGrant grant)
{
_store.AddOrUpdate(grant.Key, grant, (key, oldValue) => grant);
return Task.CompletedTask;
}
public Task<PersistedGrant> GetAsync(string key)
{
if (!_store.TryGetValue(key, out var grant))
throw new Exception($"Key '{key}' not found");
return Task.FromResult(grant);
}
public Task<IEnumerable<PersistedGrant>> GetAllAsync(PersistedGrantFilter filter)
{
var list = _store.Values.Where(x =>
(filter.ClientId.IsMissing() || filter.ClientId == x.ClientId)
&& (filter.SessionId.IsMissing() || filter.SessionId == x.SessionId)
&& (filter.SubjectId.IsMissing() || filter.SubjectId == x.SubjectId)
&& (filter.Type.IsMissing() || filter.Type == x.Type)
);
return Task.FromResult(list);
}
public Task RemoveAsync(string key)
{
_store.TryRemove(key, out _);
return Task.CompletedTask;
}
public async Task RemoveAllAsync(PersistedGrantFilter filter)
{
var list = await GetAllAsync(filter);
foreach (var item in list)
{
await RemoveAsync(item.Key);
}
}
}
+36
View File
@@ -0,0 +1,36 @@
namespace MyOffice.Web.Identity;
using Data.Repositories.Users;
using IdentityModel;
using IdentityServer4.Models;
using IdentityServer4.Services;
using System.Security.Claims;
public class ProfileService : IProfileService
{
private readonly IUserRepository _userRepository;
public ProfileService(
IUserRepository userRepository
)
{
_userRepository = userRepository;
}
public async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
var sub = context.Subject.Claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Subject);
if (sub != null && Guid.TryParse(sub.Value, out var id))
{
var user = await _userRepository.GetUserAsync(id);
if (user != null)
if (context.RequestedClaimTypes.Contains(JwtClaimTypes.Email))
context.IssuedClaims.Add(new Claim(JwtClaimTypes.Email, user.Email));
}
}
public Task IsActiveAsync(IsActiveContext context)
{
return Task.FromResult(0);
}
}
@@ -0,0 +1,83 @@
namespace MyOffice.Web.Identity.Repositories;
using System.Security.Cryptography;
using Domain;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options;
public class PasswordHasher : IPasswordHasher<ApplicationUser<Guid>>
{
public string HashPassword(ApplicationUser<Guid> user, string password)
{
byte[] salt;
salt = RandomNumberGenerator.GetBytes(16);
var pbkdf2 = new Rfc2898DeriveBytes(password, salt, 100000);
var hash = pbkdf2.GetBytes(20);
var hashBytes = new byte[36];
Array.Copy(salt, 0, hashBytes, 0, 16);
Array.Copy(hash, 0, hashBytes, 16, 20);
var passwordHash = Convert.ToBase64String(hashBytes);
return passwordHash;
}
private bool IsValidHash(string password, string passwordHash)
{
/* Fetch the stored value */
/* Extract the bytes */
var hashBytes = Convert.FromBase64String(passwordHash);
/* Get the salt */
var salt = new byte[16];
Array.Copy(hashBytes, 0, salt, 0, 16);
/* Compute the hash on the password the user entered */
var pbkdf2 = new Rfc2898DeriveBytes(password, salt, 100000);
var hash = pbkdf2.GetBytes(20);
/* Compare the results */
for (var i = 0; i < 20; i++)
if (hashBytes[i + 16] != hash[i])
return false;
return true;
}
public PasswordVerificationResult VerifyHashedPassword(
ApplicationUser<Guid> user,
string hashedPassword,
string providedPassword
)
{
if (IsValidHash(providedPassword, hashedPassword)) return PasswordVerificationResult.Success;
return PasswordVerificationResult.Failed;
}
}
public class AppUserManager : UserManager<ApplicationUser<Guid>>
{
public AppUserManager(
IUserStore<ApplicationUser<Guid>> store,
IOptions<IdentityOptions> optionsAccessor,
IPasswordHasher<ApplicationUser<Guid>> passwordHasher,
IEnumerable<IUserValidator<ApplicationUser<Guid>>> userValidators,
IEnumerable<IPasswordValidator<ApplicationUser<Guid>>> passwordValidators,
ILookupNormalizer keyNormalizer,
IdentityErrorDescriber errors,
IServiceProvider services,
ILogger<UserManager<ApplicationUser<Guid>>> logger) :
base(
store,
optionsAccessor,
passwordHasher,
userValidators,
passwordValidators,
keyNormalizer,
errors,
services,
logger
)
{
}
}
@@ -0,0 +1,62 @@
namespace MyOffice.Web.Identity.Repositories;
using Domain;
using Microsoft.AspNetCore.Identity;
public class RoleStore : IRoleStore<ApplicationRole>
{
public void Dispose()
{
}
public Task<IdentityResult> CreateAsync(ApplicationRole role, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public Task<IdentityResult> UpdateAsync(ApplicationRole role, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public Task<IdentityResult> DeleteAsync(ApplicationRole role, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public Task<string> GetRoleIdAsync(ApplicationRole role, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public Task<string> GetRoleNameAsync(ApplicationRole role, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public Task SetRoleNameAsync(ApplicationRole role, string roleName, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public Task<string> GetNormalizedRoleNameAsync(ApplicationRole role, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public Task SetNormalizedRoleNameAsync(ApplicationRole role, string normalizedName,
CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public Task<ApplicationRole> FindByIdAsync(string roleId, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public Task<ApplicationRole> FindByNameAsync(string normalizedRoleName, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
}
@@ -0,0 +1,192 @@
namespace MyOffice.Web.Identity.Repositories;
using Data.Models.Users;
using Data.Repositories.Users;
using Domain;
using Microsoft.AspNetCore.Identity;
public class UserStore :
IUserStore<ApplicationUser<Guid>>,
IUserPasswordStore<ApplicationUser<Guid>>,
IUserEmailStore<ApplicationUser<Guid>>
{
private readonly IUserRepository _userRepository;
public UserStore(
IUserRepository userRepository
)
{
_userRepository = userRepository;
}
public void Dispose()
{
}
public Task<string> GetUserIdAsync(ApplicationUser<Guid> user, CancellationToken cancellationToken)
{
return Task.FromResult(user.Id.ToString());
}
public Task<string> GetUserNameAsync(ApplicationUser<Guid> user, CancellationToken cancellationToken)
{
return Task.FromResult(user.UserName);
}
public Task SetUserNameAsync(ApplicationUser<Guid> user, string userName, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public Task<string> GetNormalizedUserNameAsync(ApplicationUser<Guid> user, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public Task SetNormalizedUserNameAsync(ApplicationUser<Guid> user, string normalizedName,
CancellationToken cancellationToken)
{
user.UserName = normalizedName;
return Task.FromResult(0);
}
public async Task<IdentityResult> CreateAsync(ApplicationUser<Guid> user, CancellationToken cancellationToken)
{
var result = await _userRepository.AddUserAsync(new User
{
Id = user.Id,
UserName = user.UserName,
Email = user.Email,
PasswordHash = user.PasswordHash,
FirstName = user.FirstName,
LastName = user.LastName,
FullName = user.FullName,
IsEmailConfirmed = user.IsEmailConfirmed
});
return result == 1 ? IdentityResult.Success : IdentityResult.Failed();
}
public async Task<IdentityResult> UpdateAsync(ApplicationUser<Guid> user, CancellationToken cancellationToken)
{
var userDb = new User
{
Id = user.Id,
UserName = user.UserName,
Email = user.Email,
PasswordHash = user.PasswordHash,
FirstName = user.FirstName,
LastName = user.LastName,
FullName = user.FullName,
IsEmailConfirmed = user.IsEmailConfirmed
};
var result = await _userRepository.UpdateUserAsync(userDb);
return result == 1 ? IdentityResult.Success : IdentityResult.Failed();
}
public Task<IdentityResult> DeleteAsync(ApplicationUser<Guid> user, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public async Task<ApplicationUser<Guid>> FindByIdAsync(string userId, CancellationToken cancellationToken)
{
var user = await _userRepository.GetUserAsync(Guid.Parse(userId));
if (user == null)
{
#pragma warning disable CS8603 // Possible null reference return.
return null;
#pragma warning restore CS8603 // Possible null reference return.
}
return new ApplicationUser<Guid>
{
Id = user.Id,
UserName = user.UserName,
Email = user.Email,
PasswordHash = user.PasswordHash,
FirstName = user.FirstName,
LastName = user.LastName,
FullName = user.FullName,
IsEmailConfirmed = user.IsEmailConfirmed
};
}
public async Task<ApplicationUser<Guid>> FindByNameAsync(string normalizedUserName,
CancellationToken cancellationToken)
{
var user = await _userRepository.GetByUserUserNameAsync(normalizedUserName);
if (user == null)
{
#pragma warning disable CS8603 // Possible null reference return.
return null;
#pragma warning restore CS8603 // Possible null reference return.
}
return new ApplicationUser<Guid>
{
Id = user.Id,
UserName = user.UserName,
Email = user.Email,
PasswordHash = user.PasswordHash,
FirstName = user.FirstName,
LastName = user.LastName,
FullName = user.FullName,
IsEmailConfirmed = user.IsEmailConfirmed
};
}
public Task SetPasswordHashAsync(ApplicationUser<Guid> user, string passwordHash,
CancellationToken cancellationToken)
{
user.PasswordHash = passwordHash;
return Task.FromResult(0);
}
public Task<string> GetPasswordHashAsync(ApplicationUser<Guid> user, CancellationToken cancellationToken)
{
return Task.FromResult(user.PasswordHash);
}
public Task<bool> HasPasswordAsync(ApplicationUser<Guid> user, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public Task SetEmailAsync(ApplicationUser<Guid> user, string email, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public Task<string> GetEmailAsync(ApplicationUser<Guid> user, CancellationToken cancellationToken)
{
return Task.FromResult(user.Email);
}
public Task<bool> GetEmailConfirmedAsync(ApplicationUser<Guid> user, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public Task SetEmailConfirmedAsync(ApplicationUser<Guid> user, bool confirmed, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
public Task<ApplicationUser<Guid>> FindByEmailAsync(string normalizedEmail, CancellationToken cancellationToken)
{
return FindByNameAsync(normalizedEmail, cancellationToken);
}
public Task<string?> GetNormalizedEmailAsync(ApplicationUser<Guid> user, CancellationToken cancellationToken)
{
return Task.FromResult(user?.Email);
}
public Task SetNormalizedEmailAsync(ApplicationUser<Guid> user, string normalizedEmail,
CancellationToken cancellationToken)
{
return Task.FromResult(0);
}
}