Private
Public Access
1
0

Add profile management (display name, email, password change, account deletion)

Full-stack profile section: DisplayName column on User model, profile CRUD
endpoints on AuthController, and complete Settings > Profile tab UI with
profile editing, password change, account info, and account deletion.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Catherine Renelle
2026-02-09 22:44:52 -05:00
parent 0562bb97b7
commit 1ceeca0fb6
12 changed files with 2250 additions and 175 deletions
+49 -1
View File
@@ -82,6 +82,54 @@ public class AuthService : IAuthService
}
}
public async Task<UserProfileResponse> GetProfileAsync(Guid userId)
{
var user = await _db.Users.FindAsync(userId)
?? throw new KeyNotFoundException("User not found");
return new UserProfileResponse(user.Username, user.DisplayName, user.Email, user.CreatedAt, user.LastLoginAt);
}
public async Task<UserProfileResponse> UpdateProfileAsync(Guid userId, UpdateProfileRequest request)
{
var user = await _db.Users.FindAsync(userId)
?? throw new KeyNotFoundException("User not found");
if (request.DisplayName != null)
user.DisplayName = request.DisplayName;
if (request.Email != null && request.Email != user.Email)
{
if (await _db.Users.AnyAsync(u => u.Email == request.Email && u.Id != userId))
throw new InvalidOperationException("Email already in use");
user.Email = request.Email;
}
await _db.SaveChangesAsync();
return new UserProfileResponse(user.Username, user.DisplayName, user.Email, user.CreatedAt, user.LastLoginAt);
}
public async Task ChangePasswordAsync(Guid userId, ChangePasswordRequest request)
{
var user = await _db.Users.FindAsync(userId)
?? throw new KeyNotFoundException("User not found");
if (!BCrypt.Net.BCrypt.Verify(request.CurrentPassword, user.PasswordHash))
throw new InvalidOperationException("Current password is incorrect");
user.PasswordHash = BCrypt.Net.BCrypt.HashPassword(request.NewPassword);
await _db.SaveChangesAsync();
}
public async Task DeleteAccountAsync(Guid userId)
{
var user = await _db.Users.FindAsync(userId)
?? throw new KeyNotFoundException("User not found");
_db.Users.Remove(user);
await _db.SaveChangesAsync();
}
private AuthResponse GenerateAuthResponse(User user)
{
var expiresAt = DateTime.UtcNow.AddHours(12);
@@ -92,7 +140,7 @@ public class AuthService : IAuthService
user.RefreshTokenExpiresAt = DateTime.UtcNow.AddDays(30);
_db.SaveChanges();
return new AuthResponse(token, refreshToken, expiresAt, user.Username);
return new AuthResponse(token, refreshToken, expiresAt, user.Username, user.DisplayName);
}
private string GenerateJwtToken(User user, DateTime expiresAt)