namespace MyOffice.Web.Controllers; using Models.Auth; using Identity.Domain; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using System; using System.ComponentModel.DataAnnotations; using Microsoft.AspNetCore.Authorization; using MyOffice.Data.Models.Users; using Core.Extensions; using MyOffice.Core.Identity; using Core; using Services.Users; using Services.Users.Domain; using MyOffice.Data.Models.Currencies; using MyOffice.Web.Infrastructure.Attributes; [DefaultFromBody] public class UserController : BaseApiController { private readonly UserManager> _userManager; private readonly UserService _userService; private readonly IEnumerable _externalProviderValidators; public UserController( UserManager> userManager, UserService userService, IEnumerable externalProviderValidators ) { _userManager = userManager; _userService = userService; _externalProviderValidators = externalProviderValidators; } public async Task Register([FromBody] RegisterModel request) { var user = new ApplicationUser { Id = Guid.NewGuid(), UserName = request.UserName, Email = request.UserName, CurrencyId = CurrencyGlobalIdEnum.USD.ToString(), }; var result = await _userManager.CreateAsync(user, request.Password); return new { result.Succeeded, Errors = result.Errors.Where(x => !x.Code.Equals("DuplicateUserName")) }; } [Authorize] public async Task ProfileGet() { var user = await _userManager.GetUserAsync(User); return user.ToModel(await _userService.GetUserExternals(user.Id)); } [Authorize] public async Task ProfileUpdate([FromBody] ProfileModel model) { var user = await _userManager.GetUserAsync(User); user.FirstName = model.FirstName; user.LastName = model.LastName; user.FullName = model.FullName.NullIfEmpty() ?? $"{model.FirstName} {model.LastName}"; user.CurrencyId = model.Currency; await _userManager.UpdateAsync(user); return user.ToModel(await _userService.GetUserExternals(user.Id)); } [Authorize] public async Task AttachProvider([FromBody] AttachModel model) { var validator = _externalProviderValidators.FirstOrDefault(x => x.Provider.EqualsIgnoreCase(model.Provider)); if (validator == null) return ProblemBadResponse("Provider not supported"); var result = await validator.ValidateAsync(model.Token); if (!result.IsSuccessed) return ProblemBadResponse("Token not valid"); var execResult = _userService.AddUserExternal(UserId, model.Provider, result.ExternalId!, result.Email!); switch (execResult.Status) { case AddUserExternalStatusEnum.success: return Ok(new { success = true }); case AddUserExternalStatusEnum.externalid_used: case AddUserExternalStatusEnum.user_not_valid: return ProblemBadResponse("Provider already connected"); default: throw new NotSupportedException(execResult.Status.ToString()); } } [Authorize] public async Task DeattachProvider([FromBody] DeattachModel model) { var exec = await _userService.RemoveUserExternal(UserId, model.Provider); if (exec.Status == GeneralExecStatus.not_found) return ProblemBadResponse("Provider not connected"); return Ok(new { success = true }); } } public class DeattachModel { [Required] public string Provider { get; set; } = null!; } public class AttachModel { [Required] public string Provider { get; set; } = null!; [Required] public string Token { get; set; } = null!; } public class ProfileModel { public class ProviderModel { public string Provider { get; set; } = null!; public DateTime CreatedOn { get; set; } } public string? Email { get; set; } public string? FirstName { get; set; } public string? LastName { get; set; } public string? FullName { get; set; } public bool? IsEmailConfirmed { get; set; } public string? Currency { get; set; } public List? Providers { get; set; } } public static class ProfileModelExtensions { public static ProfileModel ToModel(this ApplicationUser user, List userClaims) { return new ProfileModel { Email = user.Email, FirstName = user.FirstName, LastName = user.LastName, FullName = user.FullName, IsEmailConfirmed = user.IsEmailConfirmed, Currency = user.CurrencyId, Providers = userClaims?.Select(x => new ProfileModel.ProviderModel { Provider = x.Provider, CreatedOn = x.CreatedOn }).ToList() }; } }