189 lines
5.0 KiB
C#
189 lines
5.0 KiB
C#
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;
|
|
|
|
[ApiController]
|
|
[Route("api/user")]
|
|
[DefaultFromBody]
|
|
public class UserController : BaseApiController
|
|
{
|
|
private readonly UserManager<ApplicationUser<Guid>> _userManager;
|
|
private readonly UserService _userService;
|
|
private readonly IEnumerable<IExternalProviderValidator> _externalProviderValidators;
|
|
|
|
public UserController(
|
|
UserManager<ApplicationUser<Guid>> userManager,
|
|
UserService userService,
|
|
IEnumerable<IExternalProviderValidator> externalProviderValidators
|
|
)
|
|
{
|
|
_userManager = userManager;
|
|
_userService = userService;
|
|
_externalProviderValidators = externalProviderValidators;
|
|
}
|
|
|
|
[AllowAnonymous]
|
|
[HttpPost("register")]
|
|
public async Task<IActionResult> Register([FromBody] RegisterModel request)
|
|
{
|
|
if (!ModelState.IsValid)
|
|
return BadRequest(new
|
|
{
|
|
Succeeded = false,
|
|
Errors = ModelState.Values
|
|
.SelectMany(v => v.Errors)
|
|
.Select(e => new { Code = "Validation", Description = e.ErrorMessage })
|
|
});
|
|
|
|
var email = request.UserName.Trim();
|
|
var user = new ApplicationUser<Guid>
|
|
{
|
|
Id = Guid.NewGuid(),
|
|
UserName = email,
|
|
Email = email,
|
|
IsEmailConfirmed = true,
|
|
CurrencyId = CurrencyGlobalIdEnum.USD.ToString(),
|
|
};
|
|
|
|
var result = await _userManager.CreateAsync(user, request.Password);
|
|
|
|
return Ok(new
|
|
{
|
|
result.Succeeded,
|
|
Errors = result.Errors
|
|
.Where(x => !x.Code.Equals("DuplicateUserName"))
|
|
.Select(x => new { x.Code, x.Description })
|
|
});
|
|
}
|
|
|
|
[Authorize]
|
|
[HttpGet("profile")]
|
|
public async Task<object> ProfileGet()
|
|
{
|
|
var user = await _userManager.FindByIdAsync(UserId.ToString());
|
|
|
|
return user.ToModel(await _userService.GetUserExternals(user.Id));
|
|
}
|
|
|
|
[Authorize]
|
|
[HttpPost("profile")]
|
|
public async Task<object> ProfileUpdate([FromBody] ProfileModel model)
|
|
{
|
|
var user = await _userManager.FindByIdAsync(UserId.ToString()); ;
|
|
|
|
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]
|
|
[HttpPost("attach")]
|
|
public async Task<object> 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 = await _userService.AddUserExternalAsync(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]
|
|
[HttpPost("deattach")]
|
|
public async Task<object> 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<ProviderModel>? Providers { get; set; }
|
|
}
|
|
|
|
public static class ProfileModelExtensions
|
|
{
|
|
public static ProfileModel ToModel(this ApplicationUser<Guid> user, List<UserExternal> 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()
|
|
};
|
|
}
|
|
} |