Loading Kollectionized.Api/Controllers/AccountUpdateController.cs 0 → 100644 +48 −0 Original line number Diff line number Diff line using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Kollectionized.Api.Data; using Kollectionized.Api.Dtos; using Kollectionized.Api.Models; namespace Kollectionized.Api.Controllers; [ApiController] [Route("api/users")] public class AccountUpdateController(AppDbContext context) : ControllerBase { [HttpPut("{username}")] public async Task<IActionResult> UpdateAccount(string username, [FromBody] AccountUpdateDto dto) { var user = await context.Users.FirstOrDefaultAsync(u => u.Username == username); if (user == null || !BCrypt.Net.BCrypt.Verify(dto.Password, user.PasswordHash)) return Unauthorized("Invalid password."); if (!string.IsNullOrWhiteSpace(dto.NewUsername) && dto.NewUsername != username) { var exists = await context.Users.AnyAsync(u => u.Username == dto.NewUsername); if (exists) return BadRequest("Username already taken."); user.Username = dto.NewUsername; } user.Bio = dto.Bio ?? user.Bio; context.Users.Update(user); await context.SaveChangesAsync(); return Ok(new { message = "Account updated." }); } [HttpPut("{username}/password")] public async Task<IActionResult> ChangePassword(string username, [FromBody] PasswordChangeDto dto) { var user = await context.Users.FirstOrDefaultAsync(u => u.Username == username); if (user == null || !BCrypt.Net.BCrypt.Verify(dto.CurrentPassword, user.PasswordHash)) return Unauthorized("Invalid password."); user.PasswordHash = BCrypt.Net.BCrypt.HashPassword(dto.NewPassword); context.Users.Update(user); await context.SaveChangesAsync(); return Ok(new { message = "Password changed." }); } } No newline at end of file Kollectionized.Api/Dtos/AccountUpdateDto.cs 0 → 100644 +8 −0 Original line number Diff line number Diff line namespace Kollectionized.Api.Dtos; public class AccountUpdateDto { public string Password { get; set; } = string.Empty; public string? NewUsername { get; set; } public string? Bio { get; set; } } No newline at end of file Kollectionized.Api/Dtos/PasswordChangeDto.cs 0 → 100644 +7 −0 Original line number Diff line number Diff line namespace Kollectionized.Api.Dtos; public class PasswordChangeDto { public string CurrentPassword { get; set; } = string.Empty; public string NewPassword { get; set; } = string.Empty; } No newline at end of file Kollectionized/Services/UserService.cs +20 −3 Original line number Diff line number Diff line using System; using System.Collections.Generic; using System.Net.Http; using System.Net.Http.Json; Loading Loading @@ -34,10 +35,17 @@ public class UserService : ServiceBase return response.IsSuccessStatusCode ? null : await response.Content.ReadAsStringAsync(); } public async Task<string?> ChangeUsername(string currentUsername, string password, string newUsername) public async Task<string?> UpdateAccount(string username, string password, string? newUsername, string? bio) { var response = await Client.PutAsJsonAsync("auth/change-username", new { currentUsername, password, newUsername }); var payload = new { password, newUsername, bio }; var response = await Client.PutAsJsonAsync($"users/{username}", payload); return response.IsSuccessStatusCode ? null : await response.Content.ReadAsStringAsync(); } public async Task<string?> ChangePassword(string username, string currentPassword, string newPassword) { var payload = new { currentPassword, newPassword }; var response = await Client.PutAsJsonAsync($"users/{username}/password", payload); return response.IsSuccessStatusCode ? null : await response.Content.ReadAsStringAsync(); } Loading @@ -49,4 +57,13 @@ public class UserService : ServiceBase var json = await response.Content.ReadAsStringAsync(); return JsonSerializer.Deserialize<List<User>>(json) ?? []; } private class LoginResponse { public Guid UserId { get; init; } public string Username { get; init; } = string.Empty; public string Bio { get; init; } = string.Empty; public DateTime CreatedAt { get; init; } public string LastUsername { get; init; } = string.Empty; } } No newline at end of file Kollectionized/ViewModelLocator.cs +2 −2 Original line number Diff line number Diff line Loading @@ -24,8 +24,8 @@ public static class ViewModelLocator public static CardDetailsViewModel CreateCardDetailsViewModel(PokemonCard card) => new(card, CardImageService); public static UserProfileViewModel CreateUserProfile(User user, Action? onDeleteSuccess = null) => new(user, UserService, onDeleteSuccess); /*public static UserProfileViewModel CreateUserProfile(User user, Action? onDeleteSuccess = null) => new(user, UserService, onDeleteSuccess);*/ public static UserSearchViewModel UserSearch => new(UserService); Loading Loading
Kollectionized.Api/Controllers/AccountUpdateController.cs 0 → 100644 +48 −0 Original line number Diff line number Diff line using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Kollectionized.Api.Data; using Kollectionized.Api.Dtos; using Kollectionized.Api.Models; namespace Kollectionized.Api.Controllers; [ApiController] [Route("api/users")] public class AccountUpdateController(AppDbContext context) : ControllerBase { [HttpPut("{username}")] public async Task<IActionResult> UpdateAccount(string username, [FromBody] AccountUpdateDto dto) { var user = await context.Users.FirstOrDefaultAsync(u => u.Username == username); if (user == null || !BCrypt.Net.BCrypt.Verify(dto.Password, user.PasswordHash)) return Unauthorized("Invalid password."); if (!string.IsNullOrWhiteSpace(dto.NewUsername) && dto.NewUsername != username) { var exists = await context.Users.AnyAsync(u => u.Username == dto.NewUsername); if (exists) return BadRequest("Username already taken."); user.Username = dto.NewUsername; } user.Bio = dto.Bio ?? user.Bio; context.Users.Update(user); await context.SaveChangesAsync(); return Ok(new { message = "Account updated." }); } [HttpPut("{username}/password")] public async Task<IActionResult> ChangePassword(string username, [FromBody] PasswordChangeDto dto) { var user = await context.Users.FirstOrDefaultAsync(u => u.Username == username); if (user == null || !BCrypt.Net.BCrypt.Verify(dto.CurrentPassword, user.PasswordHash)) return Unauthorized("Invalid password."); user.PasswordHash = BCrypt.Net.BCrypt.HashPassword(dto.NewPassword); context.Users.Update(user); await context.SaveChangesAsync(); return Ok(new { message = "Password changed." }); } } No newline at end of file
Kollectionized.Api/Dtos/AccountUpdateDto.cs 0 → 100644 +8 −0 Original line number Diff line number Diff line namespace Kollectionized.Api.Dtos; public class AccountUpdateDto { public string Password { get; set; } = string.Empty; public string? NewUsername { get; set; } public string? Bio { get; set; } } No newline at end of file
Kollectionized.Api/Dtos/PasswordChangeDto.cs 0 → 100644 +7 −0 Original line number Diff line number Diff line namespace Kollectionized.Api.Dtos; public class PasswordChangeDto { public string CurrentPassword { get; set; } = string.Empty; public string NewPassword { get; set; } = string.Empty; } No newline at end of file
Kollectionized/Services/UserService.cs +20 −3 Original line number Diff line number Diff line using System; using System.Collections.Generic; using System.Net.Http; using System.Net.Http.Json; Loading Loading @@ -34,10 +35,17 @@ public class UserService : ServiceBase return response.IsSuccessStatusCode ? null : await response.Content.ReadAsStringAsync(); } public async Task<string?> ChangeUsername(string currentUsername, string password, string newUsername) public async Task<string?> UpdateAccount(string username, string password, string? newUsername, string? bio) { var response = await Client.PutAsJsonAsync("auth/change-username", new { currentUsername, password, newUsername }); var payload = new { password, newUsername, bio }; var response = await Client.PutAsJsonAsync($"users/{username}", payload); return response.IsSuccessStatusCode ? null : await response.Content.ReadAsStringAsync(); } public async Task<string?> ChangePassword(string username, string currentPassword, string newPassword) { var payload = new { currentPassword, newPassword }; var response = await Client.PutAsJsonAsync($"users/{username}/password", payload); return response.IsSuccessStatusCode ? null : await response.Content.ReadAsStringAsync(); } Loading @@ -49,4 +57,13 @@ public class UserService : ServiceBase var json = await response.Content.ReadAsStringAsync(); return JsonSerializer.Deserialize<List<User>>(json) ?? []; } private class LoginResponse { public Guid UserId { get; init; } public string Username { get; init; } = string.Empty; public string Bio { get; init; } = string.Empty; public DateTime CreatedAt { get; init; } public string LastUsername { get; init; } = string.Empty; } } No newline at end of file
Kollectionized/ViewModelLocator.cs +2 −2 Original line number Diff line number Diff line Loading @@ -24,8 +24,8 @@ public static class ViewModelLocator public static CardDetailsViewModel CreateCardDetailsViewModel(PokemonCard card) => new(card, CardImageService); public static UserProfileViewModel CreateUserProfile(User user, Action? onDeleteSuccess = null) => new(user, UserService, onDeleteSuccess); /*public static UserProfileViewModel CreateUserProfile(User user, Action? onDeleteSuccess = null) => new(user, UserService, onDeleteSuccess);*/ public static UserSearchViewModel UserSearch => new(UserService); Loading