IdentityUserWriter.cs 4.0 KB

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