301 lines
9.8 KiB
C#
301 lines
9.8 KiB
C#
using System.Diagnostics;
|
|
using Google.Apis.Oauth2.v2.Data;
|
|
using System.Security.Claims;
|
|
using Hutopy.Application.Common.Interfaces;
|
|
using Hutopy.Application.Common.Models;
|
|
using Hutopy.Application.Users.Models;
|
|
using Hutopy.Infrastructure.Identity.OwnedEntities;
|
|
using Hutopy.Infrastructure.Utils;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Http;
|
|
using Microsoft.AspNetCore.Identity;
|
|
using Microsoft.Extensions.Configuration;
|
|
|
|
namespace Hutopy.Infrastructure.Identity;
|
|
|
|
public class IdentityService(
|
|
UserManager<ApplicationUser> userManager,
|
|
SignInManager<ApplicationUser> signInManager,
|
|
IUserClaimsPrincipalFactory<ApplicationUser> userClaimsPrincipalFactory,
|
|
IAuthorizationService authorizationService,
|
|
IHttpContextAccessor contextAccessor,
|
|
IConfiguration configuration
|
|
)
|
|
: IIdentityService
|
|
{
|
|
public async Task<string?> GetUserNameAsync(string userId)
|
|
{
|
|
var user = await userManager.FindByIdAsync(userId);
|
|
|
|
return user?.UserName;
|
|
}
|
|
|
|
public async Task<UserModel?> GetUserByUserNameAsync(string userName)
|
|
{
|
|
var response = await userManager.FindByNameAsync(userName);
|
|
|
|
if (response == null) return null;
|
|
|
|
var userModel = new UserModel()
|
|
{
|
|
Id = response.Id,
|
|
UserName = response.UserName,
|
|
FirstName = response.FirstName,
|
|
LastName = response.LastName,
|
|
Email = response.Email,
|
|
};
|
|
|
|
return userModel;
|
|
}
|
|
|
|
public async Task<Result<string>> CreateUserAsync(Userinfo userInfo)
|
|
{
|
|
var applicationUser = new ApplicationUser
|
|
{
|
|
UserName = userInfo.Name,
|
|
Email = userInfo.Email,
|
|
FirstName = userInfo.GivenName,
|
|
LastName = userInfo.FamilyName
|
|
};
|
|
|
|
var password = Guid.NewGuid().ToString("N")[..32];
|
|
|
|
var identityResult = await userManager.CreateAsync(applicationUser, password);
|
|
|
|
var applicationResult = identityResult.ToApplicationResult();
|
|
|
|
var result = new Result<string>(applicationResult.Succeeded, applicationResult.Errors);
|
|
|
|
result.Value = applicationUser.Id;
|
|
|
|
return result;
|
|
}
|
|
|
|
public async Task<Result<string>> CreateUserAsync(string email, string userName, string firstName, string lastName, string password)
|
|
{
|
|
var applicationUser = new ApplicationUser
|
|
{
|
|
UserName = userName,
|
|
Email = email,
|
|
FirstName = firstName,
|
|
LastName = lastName
|
|
};
|
|
|
|
var response = await userManager.CreateAsync(applicationUser, password);
|
|
|
|
var result = new Result<string>(response.Succeeded, response.ToApplicationResult().Errors);
|
|
result.Value = applicationUser.Id;
|
|
|
|
return result;
|
|
}
|
|
|
|
public async Task<Result<string>> UpdateCurrentUserAsync(string id, string firstName, string lastName, string occupation,
|
|
string phoneNumber, string birthDate, string country, string city, string address, string about, string description,
|
|
SocialNetworksModel socialNetworks)
|
|
{
|
|
var applicationUser = await userManager.FindByIdAsync(id);
|
|
|
|
if (applicationUser is null) return Result<string>.Failure(new[] { "User not found." });
|
|
|
|
applicationUser.FirstName = firstName;
|
|
applicationUser.LastName = lastName;
|
|
applicationUser.Occupation = occupation;
|
|
applicationUser.PhoneNumber = phoneNumber;
|
|
applicationUser.BirthDate = birthDate;
|
|
applicationUser.Country = country;
|
|
applicationUser.City = city;
|
|
applicationUser.Address = address;
|
|
applicationUser.About = about;
|
|
applicationUser.Description = description;
|
|
applicationUser.SocialNetworks = new SocialNetworks()
|
|
{
|
|
FacebookUrl = socialNetworks.FacebookUrl,
|
|
InstagramUrl = socialNetworks.InstagramUrl,
|
|
XUrl = socialNetworks.XUrl,
|
|
LinkedInUrl = socialNetworks.LinkedInUrl,
|
|
TikTokUrl = socialNetworks.TikTokUrl,
|
|
YoutubeUrl = socialNetworks.YoutubeUrl,
|
|
RedditUrl = socialNetworks.RedditUrl,
|
|
YourWebsiteUrl = socialNetworks.YourWebsiteUrl
|
|
};
|
|
|
|
var response = await userManager.UpdateAsync(applicationUser);
|
|
|
|
var applicationResult = response.ToApplicationResult();
|
|
|
|
var result = new Result<string>(applicationResult.Succeeded,
|
|
applicationResult.Errors);
|
|
|
|
result.Value = id;
|
|
|
|
return result;
|
|
}
|
|
|
|
public async Task<UserModel?> FindUserByIdAsync(string id)
|
|
{
|
|
var response = await userManager.FindByIdAsync(id);
|
|
|
|
if (response == null) return null;
|
|
|
|
var userModel = new UserModel
|
|
{
|
|
Id = response.Id,
|
|
UserName = response.UserName,
|
|
FirstName = response.FirstName,
|
|
LastName = response.LastName,
|
|
Email = response.Email,
|
|
Occupation = response.Occupation,
|
|
Phone = response.PhoneNumber,
|
|
BirthDate = response.BirthDate,
|
|
Country = response.Country,
|
|
City = response.City,
|
|
Address = response.Address,
|
|
About = response.About,
|
|
Description = response.Description,
|
|
SocialNetworks = new SocialNetworksModel
|
|
{
|
|
FacebookUrl = response.SocialNetworks.FacebookUrl,
|
|
InstagramUrl = response.SocialNetworks.InstagramUrl,
|
|
XUrl = response.SocialNetworks.XUrl,
|
|
LinkedInUrl = response.SocialNetworks.LinkedInUrl,
|
|
TikTokUrl = response.SocialNetworks.TikTokUrl,
|
|
YoutubeUrl = response.SocialNetworks.YoutubeUrl,
|
|
RedditUrl = response.SocialNetworks.RedditUrl,
|
|
YourWebsiteUrl = response.SocialNetworks.YourWebsiteUrl,
|
|
}
|
|
};
|
|
|
|
return userModel;
|
|
}
|
|
|
|
public async Task<UserModel?> GetCurrentUserAsync()
|
|
{
|
|
var currentUserId = contextAccessor.HttpContext?.User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
|
|
if (string.IsNullOrEmpty(currentUserId))
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return await FindUserByIdAsync(currentUserId);
|
|
}
|
|
|
|
public async Task<UserModel?> FindUserByEmailAsync(string email)
|
|
{
|
|
var response = await userManager.FindByEmailAsync(email);
|
|
|
|
if (response == null) return null;
|
|
|
|
var userModel = new UserModel
|
|
{
|
|
Id = response.Id,
|
|
UserName = response.UserName,
|
|
FirstName = response.FirstName,
|
|
LastName = response.LastName,
|
|
Email = response.Email
|
|
};
|
|
|
|
return userModel;
|
|
}
|
|
|
|
public async Task<bool> IsInRoleAsync(string userId, string role)
|
|
{
|
|
var user = await userManager.FindByIdAsync(userId);
|
|
|
|
return user != null && await userManager.IsInRoleAsync(user, role);
|
|
}
|
|
|
|
public async Task<bool> CurrentUserIsInRoleAsync(string role)
|
|
{
|
|
var currentUserModel = await GetCurrentUserAsync();
|
|
var currentUser = await userManager.FindByIdAsync(currentUserModel?.Id ?? "");
|
|
|
|
return currentUser != null && await userManager.IsInRoleAsync(currentUser, role);
|
|
}
|
|
|
|
public async Task<bool> AuthorizeAsync(string userId, string policyName)
|
|
{
|
|
var user = await userManager.FindByIdAsync(userId);
|
|
|
|
if (user == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
var principal = await userClaimsPrincipalFactory.CreateAsync(user);
|
|
|
|
var result = await authorizationService.AuthorizeAsync(principal, policyName);
|
|
|
|
return result.Succeeded;
|
|
}
|
|
|
|
public async Task<Result> DeleteUserAsync(string userId)
|
|
{
|
|
var user = await userManager.FindByIdAsync(userId);
|
|
|
|
return user != null ? await DeleteUserAsync(user) : Result.Success();
|
|
}
|
|
|
|
public async Task<Result> DeleteUserAsync(ApplicationUser user)
|
|
{
|
|
var result = await userManager.DeleteAsync(user);
|
|
|
|
return result.ToApplicationResult();
|
|
}
|
|
|
|
public async Task<Result> AddRoleAsync(string userId, string role)
|
|
{
|
|
var hasAdminAccess = await CurrentUserIsInRoleAsync("Administrator");
|
|
|
|
if (!hasAdminAccess) return Result.Failure(new []{"Only administrator can assign new roles to a user."});
|
|
|
|
var user = await userManager.FindByIdAsync(userId);
|
|
|
|
if (user is null) return Result.Failure(new []{"User not found."});
|
|
|
|
var result = await userManager.AddToRoleAsync(user, role);
|
|
|
|
return result.ToApplicationResult();
|
|
}
|
|
|
|
public async Task<IList<string>> GetCurrentUserRolesAsync()
|
|
{
|
|
var currentUserModel = await GetCurrentUserAsync();
|
|
|
|
var currentUser = await userManager.FindByIdAsync(currentUserModel?.Id ?? "");
|
|
|
|
if (currentUser is null) return [];
|
|
|
|
var userRoles = await userManager.GetRolesAsync(currentUser);
|
|
|
|
return userRoles;
|
|
}
|
|
|
|
public async Task<string?> LoginAsync(string userName, string password)
|
|
{
|
|
var result = await signInManager.PasswordSignInAsync(userName, password, isPersistent: false, lockoutOnFailure: false);
|
|
|
|
if (!result.Succeeded)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
var user = await GetUserByUserNameAsync(userName);
|
|
|
|
if (user is null) throw new InvalidOperationException();
|
|
|
|
var jwtSection = configuration.GetRequiredSection("Authentication:Jwt");
|
|
|
|
var token = JwtTokenHelper.GenerateJwtToken(
|
|
issuer: jwtSection["Issuer"] ?? "",
|
|
audience: jwtSection["Audience"] ?? "",
|
|
key: jwtSection["Key"] ?? "",
|
|
userId: user.Id,
|
|
email: user.Email,
|
|
firstname: user.FirstName,
|
|
lastname: user.LastName,
|
|
portraitUrl: user.PortraitUrl);
|
|
|
|
return token;
|
|
}
|
|
}
|