Add user manager page #22
@@ -7,4 +7,7 @@ public interface IUserGateway
|
||||
{
|
||||
Task<UserListDto> GetUsers(UserFilterParams filterParams, int currentPage);
|
||||
Task<IEnumerable<RoleDto>> GetRoles();
|
||||
Task<string> CreateUser(UserDto user);
|
||||
Task<string> UpdateUser(UserDto user);
|
||||
Task<string> DeleteUser(string userId);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,32 @@ namespace GameIdeas.BlazorApp.Pages.Users.Gateways;
|
||||
|
||||
public class UserGateway(IHttpClientService httpClient) : IUserGateway
|
||||
{
|
||||
public async Task<string> CreateUser(UserDto user)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await httpClient.PostAsync<string>(Endpoints.User.Create, user)
|
||||
?? throw new InvalidOperationException(ResourcesKey.ErrorCreateUser);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw new UserCreationException(ResourcesKey.ErrorCreateUser);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<string> DeleteUser(string userId)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await httpClient.DeleteAsync<string>(Endpoints.User.Delete(userId))
|
||||
?? throw new InvalidOperationException(ResourcesKey.ErrorDeleteUser);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw new UserCreationException(ResourcesKey.ErrorDeleteUser);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<RoleDto>> GetRoles()
|
||||
{
|
||||
try
|
||||
@@ -42,4 +68,17 @@ public class UserGateway(IHttpClientService httpClient) : IUserGateway
|
||||
throw new UserNotFoundException(ResourcesKey.ErrorFetchUsers);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<string> UpdateUser(UserDto user)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await httpClient.PutAsync<string>(Endpoints.User.Update(user.Id ?? string.Empty), user)
|
||||
?? throw new InvalidOperationException(ResourcesKey.ErrorUpdateUser);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw new UserCreationException(ResourcesKey.ErrorUpdateUser);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,5 +25,9 @@ public static class Endpoints
|
||||
{
|
||||
public static string Fetch(UserFilterDto filter) => $"api/User?{UrlHelper.BuildUrlParams(filter)}";
|
||||
public const string Roles = "api/User/Roles";
|
||||
public const string Create = "api/User/Create";
|
||||
public static string Delete(string userId) => $"api/User/Delete/{userId}";
|
||||
public static string Update(string userId) => $"api/User/Update/{userId}";
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace GameIdeas.BlazorApp.Shared.Exceptions;
|
||||
|
||||
public class UserCreationException(string message) : Exception(message);
|
||||
@@ -58,6 +58,9 @@ public class Translations (TranslationService translationService)
|
||||
public string ErrorFetchUsers => translationService.Translate(nameof(ErrorFetchUsers));
|
||||
public string ErrorFetchRoles => translationService.Translate(nameof(ErrorFetchRoles));
|
||||
public string MissingField => translationService.Translate(nameof(MissingField));
|
||||
public string ErrorCreateUser => translationService.Translate(nameof(ErrorCreateUser));
|
||||
public string ErrorUpdateUser => translationService.Translate(nameof(ErrorUpdateUser));
|
||||
public string ErrorDeleteUser => translationService.Translate(nameof(ErrorDeleteUser));
|
||||
}
|
||||
|
||||
public static class ResourcesKey
|
||||
@@ -124,4 +127,7 @@ public static class ResourcesKey
|
||||
public static string ErrorFetchUsers => _instance?.ErrorFetchUsers ?? throw new InvalidOperationException("ResourcesKey.ErrorFetchUsers is not initialized.");
|
||||
public static string ErrorFetchRoles => _instance?.ErrorFetchRoles ?? throw new InvalidOperationException("ResourcesKey.ErrorFetchRoles is not initialized.");
|
||||
public static string MissingField => _instance?.MissingField ?? throw new InvalidOperationException("ResourcesKey.MissingField is not initialized.");
|
||||
public static string ErrorCreateUser => _instance?.ErrorCreateUser ?? throw new InvalidOperationException("ResourcesKey.ErrorCreateUser is not initialized.");
|
||||
public static string ErrorUpdateUser => _instance?.ErrorUpdateUser ?? throw new InvalidOperationException("ResourcesKey.ErrorUpdateUser is not initialized.");
|
||||
public static string ErrorDeleteUser => _instance?.ErrorDeleteUser ?? throw new InvalidOperationException("ResourcesKey.ErrorDeleteUser is not initialized.");
|
||||
}
|
||||
@@ -10,7 +10,8 @@ namespace GameIdeas.WebAPI.Controllers;
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
public class UserController(
|
||||
IUserService userService,
|
||||
IUserReadService userReadService,
|
||||
IUserWriteService userWriteService,
|
||||
ILoggerFactory loggerFactory) : Controller
|
||||
{
|
||||
private readonly ILogger<UserController> logger = loggerFactory.CreateLogger<UserController>();
|
||||
@@ -20,7 +21,7 @@ public class UserController(
|
||||
{
|
||||
try
|
||||
{
|
||||
return Ok(await userService.Login(model));
|
||||
return Ok(await userReadService.Login(model));
|
||||
}
|
||||
catch (UserInvalidException e)
|
||||
{
|
||||
@@ -45,7 +46,7 @@ public class UserController(
|
||||
{
|
||||
try
|
||||
{
|
||||
return Ok(await userService.GetRoles());
|
||||
return Ok(await userReadService.GetRoles());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -60,7 +61,7 @@ public class UserController(
|
||||
{
|
||||
try
|
||||
{
|
||||
return Ok(await userService.GetUsers(filter));
|
||||
return Ok(await userReadService.GetUsers(filter));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -68,4 +69,49 @@ public class UserController(
|
||||
return StatusCode(500, e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[Authorize(Roles = GlobalConstants.ADMINISTRATOR)]
|
||||
[HttpPost("Create")]
|
||||
public async Task<ActionResult<string>> CreateUser([FromBody] UserDto user)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Created("/Create", await userWriteService.CreateUser(user));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.LogError(e, "Internal error while create user");
|
||||
return StatusCode(500, e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[Authorize(Roles = GlobalConstants.ADMINISTRATOR)]
|
||||
[HttpPut("Update/{userId}")]
|
||||
public async Task<ActionResult<string>> UpdateUser(string userId, [FromBody] UserDto user)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Created("/Update", await userWriteService.UpdateUser(userId, user));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.LogError(e, "Internal error while update user");
|
||||
return StatusCode(500, e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[Authorize(Roles = GlobalConstants.ADMINISTRATOR)]
|
||||
[HttpDelete("Delete/{userId}")]
|
||||
public async Task<ActionResult<string>> DeleteUser(string userId)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Created("/Delete", await userWriteService.DeleteUser(userId));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.LogError(e, "Internal error while delete user");
|
||||
return StatusCode(500, e.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
"RequestFailedStatusFormat": "Erreur lors de la réponse, code {0}",
|
||||
"ErrorFetchCategories": "Erreur lors de la récupération des catégories",
|
||||
"PlaceholderAdd": "Ajouter un nouveau",
|
||||
"ErrorCreateGame": "Erreur lors de la Création d'un jeu",
|
||||
"ErrorCreateGame": "Erreur lors de la création d'un jeu",
|
||||
"InvalidTitle": "Le titre est incorrect",
|
||||
"InvalidInterest": "L'interêt est incorrect",
|
||||
"Unknown": "Inconnu",
|
||||
@@ -53,5 +53,8 @@
|
||||
"Roles": "Rôles",
|
||||
"ErrorFetchUsers": "Erreur lors de la récupération des utilisateurs",
|
||||
"ErrorFetchRoles": "Erreur lors de la récupération des rôles",
|
||||
"MissingField": "Un champs est manquant"
|
||||
"MissingField": "Un champs est manquant",
|
||||
"ErrorCreateUser": "Erreur lors de la création d'un utilisateur",
|
||||
"ErrorUpdateUser": "Erreur lors de la mise à jour d'un utilisateur",
|
||||
"ErrorDeleteUser": "Erreur lors de la suppression d'un utilisateur"
|
||||
}
|
||||
@@ -64,7 +64,8 @@ services.AddAuthorization();
|
||||
services.AddSingleton<TranslationService>();
|
||||
services.AddSingleton<Translations>();
|
||||
|
||||
services.AddScoped<IUserService, UserService>();
|
||||
services.AddScoped<IUserReadService, UserReadService>();
|
||||
services.AddScoped<IUserWriteService, UserWriteService>();
|
||||
services.AddScoped<IGameReadService, GameReadService>();
|
||||
services.AddScoped<IGameWriteService, GameWriteService>();
|
||||
services.AddScoped<ICategoryService, CategoryService>();
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace GameIdeas.WebAPI.Services.Users;
|
||||
|
||||
public interface IUserService
|
||||
public interface IUserReadService
|
||||
{
|
||||
Task<TokenDto> Login(UserDto user);
|
||||
Task<IEnumerable<RoleDto>> GetRoles();
|
||||
@@ -0,0 +1,10 @@
|
||||
using GameIdeas.Shared.Dto;
|
||||
|
||||
namespace GameIdeas.WebAPI.Services.Users;
|
||||
|
||||
public interface IUserWriteService
|
||||
{
|
||||
Task<string> CreateUser(UserDto user);
|
||||
Task<string> UpdateUser(string userId, UserDto user);
|
||||
Task<string> DeleteUser(string userId);
|
||||
}
|
||||
@@ -14,10 +14,10 @@ using System.Text;
|
||||
|
||||
namespace GameIdeas.WebAPI.Services.Users;
|
||||
|
||||
public class UserService(
|
||||
public class UserReadService(
|
||||
UserManager<User> userManager,
|
||||
GameIdeasContext context,
|
||||
IMapper mapper) : IUserService
|
||||
IMapper mapper) : IUserReadService
|
||||
{
|
||||
public async Task<IEnumerable<RoleDto>> GetRoles()
|
||||
{
|
||||
@@ -0,0 +1,83 @@
|
||||
using AutoMapper;
|
||||
using GameIdeas.Resources;
|
||||
using GameIdeas.Shared.Dto;
|
||||
using GameIdeas.Shared.Model;
|
||||
using GameIdeas.WebAPI.Exceptions;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
|
||||
namespace GameIdeas.WebAPI.Services.Users;
|
||||
|
||||
public class UserWriteService(
|
||||
UserManager<User> userManager) : IUserWriteService
|
||||
{
|
||||
public async Task<string> CreateUser(UserDto user)
|
||||
{
|
||||
if (user.Username == null ||
|
||||
user.Password == null ||
|
||||
user.Role == null)
|
||||
{
|
||||
throw new UserInvalidException(ResourcesKey.MissingField);
|
||||
}
|
||||
|
||||
User userToCreate = new() { UserName = user.Username };
|
||||
|
||||
var result = await userManager.CreateAsync(userToCreate, user.Password);
|
||||
|
||||
if (result.Succeeded)
|
||||
{
|
||||
await userManager.AddToRoleAsync(userToCreate, user.Role.Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new UserInvalidException(string.Join("; ", result.Errors));
|
||||
}
|
||||
|
||||
return userToCreate.Id;
|
||||
}
|
||||
|
||||
public async Task<string> DeleteUser(string userId)
|
||||
{
|
||||
if (userId == null)
|
||||
{
|
||||
throw new ArgumentNullException(ResourcesKey.MissingField);
|
||||
}
|
||||
|
||||
var user = await userManager.FindByIdAsync(userId)
|
||||
?? throw new UserInvalidException("User not found");
|
||||
|
||||
await userManager.DeleteAsync(user);
|
||||
return userId;
|
||||
}
|
||||
|
||||
public async Task<string> UpdateUser(string userId, UserDto user)
|
||||
{
|
||||
if (userId == null)
|
||||
{
|
||||
throw new ArgumentNullException(ResourcesKey.MissingField);
|
||||
}
|
||||
|
||||
var userToUpdate = await userManager.FindByIdAsync(userId)
|
||||
?? throw new UserInvalidException("User not found");
|
||||
|
||||
if (user.Username != null)
|
||||
{
|
||||
userToUpdate.UserName = user.Username;
|
||||
await userManager.UpdateAsync(userToUpdate);
|
||||
}
|
||||
|
||||
if (user.Password != null)
|
||||
{
|
||||
await userManager.RemovePasswordAsync(userToUpdate);
|
||||
await userManager.AddPasswordAsync(userToUpdate, user.Password);
|
||||
}
|
||||
|
||||
if (user.Role != null)
|
||||
{
|
||||
var roles = await userManager.GetRolesAsync(userToUpdate);
|
||||
await userManager.RemoveFromRolesAsync(userToUpdate, roles);
|
||||
await userManager.AddToRoleAsync(userToUpdate, user.Role.Name);
|
||||
}
|
||||
|
||||
return userToUpdate.Id;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user