Add project files.
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
namespace MyOffice.Web.Controllers;
|
||||
|
||||
using System.Security.Authentication;
|
||||
using Core.Extensions;
|
||||
using IdentityModel;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using static IdentityServer4.Models.IdentityResources;
|
||||
|
||||
public class BaseApiController : ControllerBase
|
||||
{
|
||||
public Guid UserId
|
||||
{
|
||||
get
|
||||
{
|
||||
var subject = User.Claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Subject)?.Value;
|
||||
if (subject.IsPresent() && Guid.TryParse(subject, out var guid)) return guid;
|
||||
|
||||
throw new AuthenticationException("Get UserId failed");
|
||||
}
|
||||
}
|
||||
|
||||
public ObjectResult ProblemBadRequest(string? detail = null)
|
||||
{
|
||||
return Problem(detail, statusCode: StatusCodes.Status400BadRequest);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
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;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
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;
|
||||
}
|
||||
|
||||
[HttpPost("~/api/user/register")]
|
||||
public async Task<object> Register([FromBody] RegisterModel request)
|
||||
{
|
||||
var user = new ApplicationUser<Guid>
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
UserName = request.UserName,
|
||||
Email = request.UserName
|
||||
};
|
||||
|
||||
var result = await _userManager.CreateAsync(user, request.Password);
|
||||
|
||||
return new
|
||||
{
|
||||
result.Succeeded,
|
||||
Errors = result.Errors.Where(x => !x.Code.Equals("DuplicateUserName"))
|
||||
};
|
||||
}
|
||||
|
||||
[Authorize]
|
||||
[HttpGet("~/api/user/profile")]
|
||||
public async Task<object> ProfileGet()
|
||||
{
|
||||
var user = await _userManager.GetUserAsync(User);
|
||||
|
||||
return user.ToModel(await _userService.GetUserExternals(user.Id));
|
||||
}
|
||||
|
||||
[Authorize]
|
||||
[HttpPost("~/api/user/profile")]
|
||||
public async Task<object> 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}";
|
||||
|
||||
await _userManager.UpdateAsync(user);
|
||||
|
||||
return user.ToModel(await _userService.GetUserExternals(user.Id));
|
||||
}
|
||||
|
||||
[Authorize]
|
||||
[HttpPost("~/api/user/attach")]
|
||||
public async Task<object> AttachProvider([FromBody] AttachModel model)
|
||||
{
|
||||
var validator = _externalProviderValidators.FirstOrDefault(x => x.Provider.EqualsIgnoreCase(model.Provider));
|
||||
if (validator == null) return ProblemBadRequest("Provider not supported");
|
||||
|
||||
var result = await validator.ValidateAsync(model.Token);
|
||||
if (!result.IsSuccessed) return ProblemBadRequest("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 ProblemBadRequest("Provider already connected");
|
||||
|
||||
default:
|
||||
throw new NotSupportedException(execResult.Status.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
[Authorize]
|
||||
[HttpPost("~/api/user/deattach")]
|
||||
public async Task<object> DeattachProvider([FromBody] DeattachModel model)
|
||||
{
|
||||
var exec = await _userService.RemoveUserExternal(UserId, model.Provider);
|
||||
|
||||
if (exec.Status == GeneralExecStatus.not_found) return ProblemBadRequest("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 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,
|
||||
Providers = userClaims?.Select(x => new ProfileModel.ProviderModel
|
||||
{
|
||||
Provider = x.Provider,
|
||||
CreatedOn = x.CreatedOn
|
||||
}).ToList()
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
namespace MyOffice.Web.Controllers;
|
||||
|
||||
using Models.WeatherForecast;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
[ApiController]
|
||||
[Route("[controller]")]
|
||||
public class WeatherForecastController : ControllerBase
|
||||
{
|
||||
private static readonly string[] Summaries = new[]
|
||||
{
|
||||
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
|
||||
};
|
||||
|
||||
private readonly ILogger<WeatherForecastController> _logger;
|
||||
|
||||
public WeatherForecastController(ILogger<WeatherForecastController> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
[HttpGet("~/api/weatherforecast")]
|
||||
public IEnumerable<WeatherForecast> Get()
|
||||
{
|
||||
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
|
||||
{
|
||||
Date = DateTime.Now.AddDays(index),
|
||||
TemperatureC = Random.Shared.Next(-20, 55),
|
||||
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
|
||||
})
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
[HttpGet("~/api/weatherforecast/auth")]
|
||||
[Authorize]
|
||||
public IEnumerable<WeatherForecast> GetAuth()
|
||||
{
|
||||
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
|
||||
{
|
||||
Date = DateTime.Now.AddDays(index),
|
||||
TemperatureC = Random.Shared.Next(-20, 55),
|
||||
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
|
||||
})
|
||||
.ToArray();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user