2024-08-13 12:29:01 +01:00
|
|
|
|
using API.Models;
|
|
|
|
|
using API.Persistence.Repositories;
|
2024-09-04 13:32:53 +01:00
|
|
|
|
using API.Persistence.Services;
|
2024-08-13 12:29:01 +01:00
|
|
|
|
using Microsoft.AspNetCore.Mvc;
|
2024-08-26 14:49:06 +01:00
|
|
|
|
using System.Text.RegularExpressions;
|
2024-08-13 12:29:01 +01:00
|
|
|
|
|
|
|
|
|
namespace API.Application.Users.Commands
|
|
|
|
|
{
|
|
|
|
|
public class UpdateUser
|
|
|
|
|
{
|
|
|
|
|
private readonly IUserRepository _repository;
|
2024-09-04 13:32:53 +01:00
|
|
|
|
private readonly R2Service _r2Service;
|
|
|
|
|
private readonly string _accessKey;
|
|
|
|
|
private readonly string _secretKey;
|
2024-08-13 12:29:01 +01:00
|
|
|
|
|
2024-09-04 13:32:53 +01:00
|
|
|
|
public UpdateUser(IUserRepository repository, AppConfiguration config)
|
2024-08-13 12:29:01 +01:00
|
|
|
|
{
|
|
|
|
|
_repository = repository;
|
2024-09-04 13:32:53 +01:00
|
|
|
|
_accessKey = config.AccessKey;
|
|
|
|
|
_secretKey = config.SecretKey;
|
|
|
|
|
_r2Service = new R2Service(_accessKey, _secretKey);
|
2024-08-13 12:29:01 +01:00
|
|
|
|
}
|
|
|
|
|
|
2024-08-27 12:06:31 +01:00
|
|
|
|
public async Task<IActionResult> Handle(UpdateUserDTO updateUserDTO)
|
2024-08-13 12:29:01 +01:00
|
|
|
|
{
|
2024-08-27 12:06:31 +01:00
|
|
|
|
User currentUser = await _repository.QueryUserByIdAsync(updateUserDTO.Id);
|
2024-08-13 12:29:01 +01:00
|
|
|
|
|
2024-09-05 10:38:47 +01:00
|
|
|
|
if (updateUserDTO.Username != null || updateUserDTO.Email != null)
|
2024-08-13 12:29:01 +01:00
|
|
|
|
{
|
2024-09-05 10:38:47 +01:00
|
|
|
|
List<User> existingUsers = await _repository.QueryAllUsersAsync();
|
2024-08-13 12:29:01 +01:00
|
|
|
|
|
2024-09-05 10:38:47 +01:00
|
|
|
|
foreach (User existingUser in existingUsers)
|
2024-08-13 12:29:01 +01:00
|
|
|
|
{
|
2024-09-05 10:38:47 +01:00
|
|
|
|
if (existingUser.Username == updateUserDTO.Username && existingUser.Username != currentUser.Username)
|
|
|
|
|
{
|
|
|
|
|
return new ConflictObjectResult(new { message = "Username is already in use." });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (existingUser.Email == updateUserDTO.Email && existingUser.Email != currentUser.Email)
|
|
|
|
|
{
|
|
|
|
|
return new ConflictObjectResult(new { message = "Email is already in use." });
|
|
|
|
|
}
|
2024-08-13 12:29:01 +01:00
|
|
|
|
}
|
2024-09-05 10:38:47 +01:00
|
|
|
|
|
|
|
|
|
if (updateUserDTO.Username != null)
|
|
|
|
|
currentUser.Username = updateUserDTO.Username;
|
|
|
|
|
if (updateUserDTO.Email != null)
|
|
|
|
|
currentUser.Email = updateUserDTO.Email;
|
2024-08-13 12:29:01 +01:00
|
|
|
|
}
|
2024-09-05 10:38:47 +01:00
|
|
|
|
|
|
|
|
|
if (updateUserDTO.Password != null)
|
2024-08-27 12:06:31 +01:00
|
|
|
|
{
|
|
|
|
|
if (IsPasswordSecure(updateUserDTO.Password))
|
|
|
|
|
{
|
|
|
|
|
string hashedPassword = BCrypt.Net.BCrypt.HashPassword(updateUserDTO.Password);
|
|
|
|
|
currentUser.HashedPassword = hashedPassword;
|
|
|
|
|
}
|
2024-09-04 13:32:53 +01:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return new ConflictObjectResult(new { message = "Password is not secure." });
|
|
|
|
|
}
|
2024-08-27 12:06:31 +01:00
|
|
|
|
}
|
2024-09-05 10:38:47 +01:00
|
|
|
|
|
2024-08-27 12:06:31 +01:00
|
|
|
|
|
2024-09-04 13:32:53 +01:00
|
|
|
|
string imageUrl = null;
|
|
|
|
|
if (updateUserDTO.ProfilePicture != null && updateUserDTO.ProfilePicture.Length > 0)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
using (var fileStream = updateUserDTO.ProfilePicture.OpenReadStream())
|
|
|
|
|
{
|
2024-09-05 10:38:47 +01:00
|
|
|
|
imageUrl = await _r2Service.UploadToR2(fileStream, "PP" + updateUserDTO.Id+".png");
|
2024-09-04 13:32:53 +01:00
|
|
|
|
currentUser.ProfilePicture = imageUrl;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
return new StatusCodeResult(StatusCodes.Status500InternalServerError);
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-08-13 12:29:01 +01:00
|
|
|
|
|
|
|
|
|
bool success = await _repository.UpdateUserAsync(currentUser);
|
|
|
|
|
if (success)
|
|
|
|
|
return new OkResult();
|
|
|
|
|
else
|
|
|
|
|
return new StatusCodeResult(StatusCodes.Status500InternalServerError);
|
|
|
|
|
|
|
|
|
|
}
|
2024-08-26 14:49:06 +01:00
|
|
|
|
private bool IsPasswordSecure(string password)
|
|
|
|
|
{
|
|
|
|
|
var hasUpperCase = new Regex(@"[A-Z]+");
|
|
|
|
|
var hasLowerCase = new Regex(@"[a-z]+");
|
|
|
|
|
var hasDigits = new Regex(@"[0-9]+");
|
|
|
|
|
var hasSpecialChar = new Regex(@"[\W_]+");
|
|
|
|
|
var hasMinimum8Chars = new Regex(@".{8,}");
|
|
|
|
|
|
|
|
|
|
return hasUpperCase.IsMatch(password)
|
|
|
|
|
&& hasLowerCase.IsMatch(password)
|
|
|
|
|
&& hasDigits.IsMatch(password)
|
|
|
|
|
&& hasSpecialChar.IsMatch(password)
|
|
|
|
|
&& hasMinimum8Chars.IsMatch(password);
|
|
|
|
|
}
|
2024-08-13 12:29:01 +01:00
|
|
|
|
}
|
|
|
|
|
}
|