IdentityUserWriter.cs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. using Application.Abstractions.Identity;
  2. using Application.Abstractions.Identity.Models;
  3. using Microsoft.AspNetCore.Identity;
  4. using Microsoft.EntityFrameworkCore;
  5. namespace Infrastructure.Persistence.Identity
  6. {
  7. public sealed class IdentityUserWriter(UserManager<ApplicationUser> userManager) : IIdentityUserWriter
  8. {
  9. public async Task UpdateUserAsync(ApplicationUserDto a, CancellationToken ct)
  10. {
  11. if (string.IsNullOrWhiteSpace(a.ID))
  12. {
  13. throw new InvalidOperationException("ID는 필수입니다.");
  14. }
  15. var user = await userManager.FindByIdAsync(a.ID);
  16. if (user is null)
  17. {
  18. throw new InvalidOperationException("사용자 정보를 찾을 수 없습니다.");
  19. }
  20. // 이메일 중복 확인(본인 제외)
  21. if (!string.IsNullOrWhiteSpace(a.Email))
  22. {
  23. var exists = await userManager.Users.AsNoTracking().AnyAsync(u => u.Email == a.Email && u.Id != a.ID, ct);
  24. if (exists)
  25. {
  26. throw new InvalidOperationException("이미 존재하는 이메일 주소입니다.");
  27. }
  28. }
  29. user.SetFullName(a.Name);
  30. user.SetEmail(a.Email);
  31. user.SetPhoneNumber(a.Phone);
  32. user.SetDeleted(a.IsDeleted);
  33. user.SetEmailConfirmed(a.EmailConfirmed);
  34. user.SetLockoutEnd(a.LockoutEnd);
  35. // 비밀번호 변경(입력되었을 때만)
  36. if (!string.IsNullOrWhiteSpace(a.NewPassword))
  37. {
  38. if (a.NewPassword != a.ConfirmPassword)
  39. {
  40. throw new InvalidOperationException("두 비밀번호가 서로 일치하지 않습니다.");
  41. }
  42. var token = await userManager.GeneratePasswordResetTokenAsync(user);
  43. var reset = await userManager.ResetPasswordAsync(user, token, a.NewPassword);
  44. if (!reset.Succeeded)
  45. {
  46. throw new InvalidOperationException(string.Join(Environment.NewLine, reset.Errors.Select(x => x.Description)));
  47. }
  48. }
  49. var updated = await userManager.UpdateAsync(user);
  50. if (!updated.Succeeded)
  51. {
  52. throw new InvalidOperationException(string.Join(Environment.NewLine, updated.Errors.Select(x => x.Description)));
  53. }
  54. }
  55. public async Task UpdateUserRolesAsync(string userID, UserRolesDto? b, CancellationToken ct)
  56. {
  57. if (string.IsNullOrWhiteSpace(userID))
  58. {
  59. throw new InvalidOperationException("ID는 필수입니다.");
  60. }
  61. var user = await userManager.FindByIdAsync(userID);
  62. if (user is null)
  63. {
  64. throw new InvalidOperationException("사용자 정보를 찾을 수 없습니다.");
  65. }
  66. var userRoles = await userManager.GetRolesAsync(user);
  67. foreach (var role in b?.Roles ?? Enumerable.Empty<UserRolesDto.Checkbox>())
  68. {
  69. var roleName = role.DisplayValue?.Trim();
  70. if (string.IsNullOrWhiteSpace(roleName))
  71. {
  72. continue;
  73. }
  74. // 현재 사용자의 역할에 포함되어 있으나 선택되지 않은 경우 제거
  75. if (userRoles.Contains(roleName, StringComparer.OrdinalIgnoreCase) && !role.IsSelected)
  76. {
  77. var removed = await userManager.RemoveFromRoleAsync(user, roleName);
  78. if (!removed.Succeeded)
  79. {
  80. throw new InvalidOperationException(string.Join(Environment.NewLine, removed.Errors.Select(e => e.Description)));
  81. }
  82. }
  83. // 현재 사용자의 역할에 포함되지 않았으나 선택된 경우 추가
  84. if (!userRoles.Contains(roleName, StringComparer.OrdinalIgnoreCase) && role.IsSelected)
  85. {
  86. var added = await userManager.AddToRoleAsync(user, roleName);
  87. if (!added.Succeeded)
  88. {
  89. throw new InvalidOperationException(string.Join(Environment.NewLine, added.Errors.Select(e => e.Description)));
  90. }
  91. }
  92. }
  93. }
  94. }
  95. }