transactions
This commit is contained in:
11
back/services/bussines/Errors.cs
Normal file
11
back/services/bussines/Errors.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using System.Net;
|
||||
|
||||
namespace back.services.bussines;
|
||||
|
||||
public static class Errors
|
||||
{
|
||||
public static readonly HttpErrorMap Unauthorized =
|
||||
new(HttpStatusCode.Unauthorized, "Invalid user data. Email or password are wrong.");
|
||||
public static readonly HttpErrorMap BadRequest =
|
||||
new(HttpStatusCode.BadRequest, "Missing user data.");
|
||||
}
|
5
back/services/bussines/HttpErrorMap.cs
Normal file
5
back/services/bussines/HttpErrorMap.cs
Normal file
@@ -0,0 +1,5 @@
|
||||
using System.Net;
|
||||
|
||||
namespace back.services.bussines;
|
||||
|
||||
public record HttpErrorMap(HttpStatusCode Code, string Description);
|
16
back/services/bussines/PhotoService/IPhotoService.cs
Normal file
16
back/services/bussines/PhotoService/IPhotoService.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using back.DataModels;
|
||||
using back.DTO;
|
||||
using DependencyInjector.Abstractions.ClassTypes;
|
||||
using DependencyInjector.Lifetimes;
|
||||
|
||||
namespace back.services.bussines.PhotoService;
|
||||
|
||||
public interface IPhotoService: IScoped
|
||||
{
|
||||
Task<Photo?> Create(PhotoFormModel form);
|
||||
Task Delete(string id, string userId = "00000000-0000-0000-0000-000000000001");
|
||||
Task<Photo?> Get(string id, string userId = "00000000-0000-0000-0000-000000000001");
|
||||
Task<(string? mediaType, byte[]? fileBytes)> GetBytes(string id, string res = "");
|
||||
Task<(int totalItems, IEnumerable<Photo>? pageData)> GetPage(int page, int pageSize);
|
||||
Task<Photo?> Update(Photo photo, string userId = "00000000-0000-0000-0000-000000000001");
|
||||
}
|
82
back/services/bussines/PhotoService/PhotoService.cs
Normal file
82
back/services/bussines/PhotoService/PhotoService.cs
Normal file
@@ -0,0 +1,82 @@
|
||||
using back.DataModels;
|
||||
using back.DTO;
|
||||
using back.persistance.blob;
|
||||
using back.persistance.data.repositories.Abstracts;
|
||||
|
||||
namespace back.services.bussines.PhotoService;
|
||||
|
||||
public class PhotoService(
|
||||
IPhotoRepository photoRepository,
|
||||
IUserRepository userRepository,
|
||||
IBlobStorageService blobStorageService
|
||||
) : IPhotoService
|
||||
{
|
||||
public async Task<Photo?> Create(PhotoFormModel form)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(form);
|
||||
if (form.Image == null || form.Image.Length == 0)
|
||||
throw new ArgumentException("No image uploaded.", nameof(form));
|
||||
//if (string.IsNullOrEmpty(form.UserId) || await userRepository.IsContentManager(form.UserId))
|
||||
// throw new ArgumentException("Invalid user ID or user is not a content manager.", nameof(form.UserId));
|
||||
|
||||
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public async Task Delete(string id, string userId = User.SystemUserId)
|
||||
{
|
||||
//if (string.IsNullOrEmpty(userId) || await userRepository.IsContentManager(userId))
|
||||
// throw new ArgumentException("Invalid user ID or user is not a content manager.", nameof(userId));
|
||||
photoRepository.Delete(id);
|
||||
}
|
||||
|
||||
public async Task<Photo?> Get(string id, string userId = User.SystemUserId)
|
||||
{
|
||||
Photo? photo = await photoRepository.GetById(id);
|
||||
return photo;
|
||||
//return photo?.CanBeSeenBy(userId) ?? false
|
||||
// ? photo
|
||||
// : null;
|
||||
}
|
||||
|
||||
public async Task<(string? mediaType, byte[]? fileBytes)> GetBytes(string id, string res = "")
|
||||
{
|
||||
var photo = await photoRepository.GetById(id);
|
||||
if (photo == null)
|
||||
return (null, null);
|
||||
|
||||
string filePath = res.ToLower() switch
|
||||
{
|
||||
"high" => photo.HighResUrl,
|
||||
"mid" => photo.MidResUrl,
|
||||
"low" or _ => photo.LowResUrl
|
||||
};
|
||||
|
||||
string? mediaType = res.ToLower() switch
|
||||
{
|
||||
"high" => $"image/{photo.Extension}",
|
||||
"mid" or "low" or _ => "image/webp",
|
||||
};
|
||||
|
||||
return (
|
||||
mediaType,
|
||||
await blobStorageService.GetBytes(filePath) ?? throw new FileNotFoundException("File not found.", filePath)
|
||||
);
|
||||
}
|
||||
|
||||
public async Task<(int totalItems, IEnumerable<Photo>? pageData)> GetPage(int page, int pageSize)
|
||||
{
|
||||
return (
|
||||
totalItems: await photoRepository.GetTotalItems(),
|
||||
pageData: photoRepository.GetPage(page, pageSize)
|
||||
);
|
||||
}
|
||||
|
||||
public async Task<Photo?> Update(Photo photo, string userId = "00000000-0000-0000-0000-000000000001")
|
||||
{
|
||||
//if (string.IsNullOrEmpty(userId) || await userRepository.IsContentManager(userId))
|
||||
// throw new ArgumentException("Invalid user ID or user is not a content manager.", nameof(userId));
|
||||
return await photoRepository.Update(photo);
|
||||
}
|
||||
}
|
14
back/services/bussines/UserService/IUserService.cs
Normal file
14
back/services/bussines/UserService/IUserService.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using back.DataModels;
|
||||
using DependencyInjector.Abstractions.ClassTypes;
|
||||
using DependencyInjector.Lifetimes;
|
||||
|
||||
namespace back.services.bussines.UserService;
|
||||
|
||||
public interface IUserService: IScoped
|
||||
{
|
||||
Task<User?> Create(string clientId, User user);
|
||||
Task<User?> Login(string email, string password, string clientId);
|
||||
Task SendResetPassword(string email);
|
||||
Task<User?> Update(User user);
|
||||
Task<User?> ValidateSystemUser(string email, string password, string systemKey, string clientId);
|
||||
}
|
133
back/services/bussines/UserService/UserService.cs
Normal file
133
back/services/bussines/UserService/UserService.cs
Normal file
@@ -0,0 +1,133 @@
|
||||
using back.DataModels;
|
||||
using back.persistance.blob;
|
||||
using back.persistance.data.repositories.Abstracts;
|
||||
using back.services.engine.Crypto;
|
||||
using back.services.engine.mailing;
|
||||
using System.Text;
|
||||
|
||||
namespace back.services.bussines.UserService;
|
||||
|
||||
public class UserService(
|
||||
IUserRepository userRepository, ICryptoService cryptoService,
|
||||
IEmailService emailService,
|
||||
IBlobStorageService blobStorageService
|
||||
) : IUserService
|
||||
{
|
||||
private readonly IUserRepository _repository = userRepository ?? throw new ArgumentNullException(nameof(userRepository));
|
||||
private readonly ICryptoService _cryptoService = cryptoService;
|
||||
private readonly IEmailService _emailService = emailService;
|
||||
private readonly IBlobStorageService _blobStorageService = blobStorageService;
|
||||
|
||||
public async Task<User?> Create(string clientId, User user)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(user);
|
||||
|
||||
if (user.Id != null && await _repository.Exists(user.Id))
|
||||
{
|
||||
return await _repository.GetById(user.Id);
|
||||
}
|
||||
if (string.IsNullOrEmpty(user.Email) || string.IsNullOrEmpty(user.Password))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (await _repository.Exists(user.Email))
|
||||
{
|
||||
return await _repository.GetByEmail(user.Email);
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(user.Salt))
|
||||
{
|
||||
user.Salt = _cryptoService.Salt();
|
||||
}
|
||||
user.Password = _cryptoService.Decrypt(clientId, user.Password) ?? string.Empty;
|
||||
user.Password = _cryptoService.HashPassword(user.Password, user.Salt) ?? string.Empty;
|
||||
|
||||
user.CreatedAt = DateTimeOffset.UtcNow.ToString("dd-MM-yyyy HH:mm:ss zz");
|
||||
|
||||
//user.Roles.Add(Role.UserRole);
|
||||
|
||||
await _repository.Insert(user);
|
||||
await _repository.SaveChanges();
|
||||
return user;
|
||||
}
|
||||
|
||||
public async Task<User?> Update(User user)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(user);
|
||||
if (user.Id == null || !await _repository.Exists(user.Id))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var existingUser = await _repository.GetById(user.Id);
|
||||
if (existingUser == null) return null;
|
||||
existingUser.Email = user.Email;
|
||||
await _repository.Update(existingUser);
|
||||
await _repository.SaveChanges();
|
||||
return existingUser;
|
||||
}
|
||||
|
||||
public async Task<User?> Login(string email, string password, string clientId)
|
||||
{
|
||||
if (string.IsNullOrEmpty(email) || string.IsNullOrEmpty(password)) return null;
|
||||
|
||||
try
|
||||
{
|
||||
var decryptedPass = _cryptoService.Decrypt(clientId, password);
|
||||
var salt = await _repository.GetUserSaltByEmail(email);
|
||||
var hashedPassword = _cryptoService.HashPassword(decryptedPass, salt);
|
||||
var user = await _repository.Login(email, hashedPassword ?? string.Empty);
|
||||
return user;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task SendResetPassword(string email)
|
||||
{
|
||||
var exists = await _repository.ExistsByEmail(email);
|
||||
if (!exists)
|
||||
{
|
||||
return;
|
||||
}
|
||||
await _emailService.SendEmailAsync(
|
||||
tos: email,
|
||||
from: "admin@mmorales.photo",
|
||||
subject: "Reset Password",
|
||||
body: "If you received this email, it means that you have requested a password reset. Please follow the instructions in the email to reset your password."
|
||||
);
|
||||
}
|
||||
|
||||
public async Task<User?> ValidateSystemUser(string email, string password, string systemKey, string clientId)
|
||||
{
|
||||
password = _cryptoService.Decrypt(clientId, password) ?? string.Empty;
|
||||
systemKey = _cryptoService.Decrypt(clientId, systemKey) ?? string.Empty;
|
||||
if (string.IsNullOrEmpty(email) || string.IsNullOrEmpty(password) || string.IsNullOrEmpty(systemKey))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (!email.Equals("@system", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var systemKeyBytes = await _blobStorageService.GetBytes("systemkey.lock");
|
||||
var systemKeyString = Encoding.UTF8.GetString(systemKeyBytes ?? []);
|
||||
var systemKeyObject = System.Text.Json.JsonSerializer.Deserialize<SystemKey>(systemKeyString);
|
||||
if (systemKeyObject == null || !systemKeyObject.IsValid(email, password, systemKey))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (!await _repository.ExistsByEmail(email))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var user = await _repository.GetByEmail(email);
|
||||
if (user == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return await Login(user.Email!, user.Password!, clientId);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user