finalizare 1.0
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
||||
namespace Application.Endpoints.Appointments;
|
||||
|
||||
public class AppointmentManagementDto
|
||||
public class AppointmentInformation
|
||||
{
|
||||
public Guid DoctorId { get; set; }
|
||||
public Guid PatientId { get; set; }
|
||||
@@ -1,165 +0,0 @@
|
||||
using Application.Services.Database.MongoDB;
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
using Core.Entities;
|
||||
|
||||
namespace Application.Endpoints.Appointments;
|
||||
|
||||
public class AppointmentManagementHandler
|
||||
{
|
||||
private readonly IAppointmentsMongoDbService _appointmentsMongoDbService;
|
||||
private readonly IDoctorRepository _doctorRepository;
|
||||
private readonly IPatientRepository _patientRepository;
|
||||
|
||||
public AppointmentManagementHandler(IAppointmentsMongoDbService appointmentsMongoDbService,
|
||||
IPatientRepository patientRepository, IDoctorRepository doctorRepository)
|
||||
{
|
||||
_appointmentsMongoDbService = appointmentsMongoDbService;
|
||||
_patientRepository = patientRepository;
|
||||
_doctorRepository = doctorRepository;
|
||||
}
|
||||
|
||||
public async Task<BaseResponse> HandleCreateAppointment(AppointmentManagementDto dto)
|
||||
{
|
||||
var validation = new CreateAppointmentValidator(_appointmentsMongoDbService,
|
||||
_doctorRepository, _patientRepository);
|
||||
var validationResult = await validation.ValidateAsync(dto);
|
||||
|
||||
if (!validationResult.IsValid)
|
||||
{
|
||||
var firstError = validationResult.Errors.FirstOrDefault();
|
||||
var errorCode = int.TryParse(firstError.ErrorCode, out var code) ? code : -1;
|
||||
var errorMessage = firstError.ErrorMessage;
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = errorCode,
|
||||
Message = errorMessage,
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
var appointmentId = IdentifierGenerator.GenerateId(dto.DoctorId, dto.PatientId);
|
||||
var criteria = new List<(string FieldName, string Value)>
|
||||
{
|
||||
("_id", appointmentId)
|
||||
};
|
||||
var appointments = await _appointmentsMongoDbService.FindAsync<Appointment>(criteria);
|
||||
|
||||
if (!appointments.Any())
|
||||
{
|
||||
var appointment = new Appointment();
|
||||
appointment.SetId(appointmentId);
|
||||
appointment.SetDoctorIid(dto.DoctorId.ToString());
|
||||
appointment.SetPatientId(dto.PatientId.ToString());
|
||||
appointment.AddAppointment(dto.Appointment);
|
||||
|
||||
await _appointmentsMongoDbService.AddAsync(appointment);
|
||||
}
|
||||
else
|
||||
{
|
||||
var appointment = appointments[0];
|
||||
appointment.AddAppointment(dto.Appointment);
|
||||
await _appointmentsMongoDbService.ModifyAsync("_id", appointmentId, appointment);
|
||||
}
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.Created,
|
||||
Message = "Appointment successfully created.",
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<BaseResponse> HandleDeleteAppointment(AppointmentManagementDto dto)
|
||||
{
|
||||
var validation = new DeleteAppointmentValidator(_appointmentsMongoDbService,
|
||||
_doctorRepository, _patientRepository);
|
||||
var validationResult = await validation.ValidateAsync(dto);
|
||||
|
||||
if (!validationResult.IsValid)
|
||||
{
|
||||
var firstError = validationResult.Errors.FirstOrDefault();
|
||||
var errorCode = int.TryParse(firstError.ErrorCode, out var code) ? code : -1;
|
||||
var errorMessage = firstError.ErrorMessage;
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = errorCode,
|
||||
Message = errorMessage,
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
var appointmentId = IdentifierGenerator.GenerateId(dto.DoctorId, dto.PatientId);
|
||||
var criteria = new List<(string FieldName, string Value)>
|
||||
{
|
||||
("_id", appointmentId)
|
||||
};
|
||||
var appointments = await _appointmentsMongoDbService.FindAsync<Appointment>(criteria);
|
||||
|
||||
if (!appointments.Any())
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NotFound,
|
||||
Message = "Appointment not found in system.",
|
||||
Data = null
|
||||
};
|
||||
|
||||
var appointment = appointments[0];
|
||||
appointment.RemoveAppointment(dto.Appointment);
|
||||
await _appointmentsMongoDbService.ModifyAsync("_id", appointmentId, appointment);
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.OK,
|
||||
Message = "Appointment successfully removed.",
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<BaseResponse> HandleGetAppointmentsByPatientId(Guid patientId)
|
||||
{
|
||||
var criteria = new List<(string FieldName, string Value)>
|
||||
{
|
||||
("PatientId", patientId.ToString())
|
||||
};
|
||||
var appointments = await _appointmentsMongoDbService.FindAsync<Appointment>(criteria);
|
||||
|
||||
if (appointments.Count == 0)
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NotFound,
|
||||
Message = $"Appointments not found in system for patient with id {patientId}.",
|
||||
Data = null
|
||||
};
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.OK,
|
||||
Message = $"Appointments for patient with id {patientId} successfully retrieved.",
|
||||
Data = appointments
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<BaseResponse> HandleGetAppointmentsByDoctorId(Guid doctorId)
|
||||
{
|
||||
var criteria = new List<(string FieldName, string Value)>
|
||||
{
|
||||
("DoctorId", doctorId.ToString())
|
||||
};
|
||||
var appointments = await _appointmentsMongoDbService.FindAsync<Appointment>(criteria);
|
||||
|
||||
if (appointments.Count == 0)
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NotFound,
|
||||
Message = $"Appointments not found in system for doctor with id {doctorId}.",
|
||||
Data = null
|
||||
};
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.OK,
|
||||
Message = $"Appointments for doctor with id {doctorId} successfully retrieved.",
|
||||
Data = appointments
|
||||
};
|
||||
}
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
using Application.Services.Database.MongoDB;
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
using Domain.Entities;
|
||||
|
||||
namespace Application.Endpoints.Appointments.CreateAppointment;
|
||||
|
||||
public class CreateAppointmentHandler(
|
||||
IAppointmentsMongoDbService appointmentsMongoDbService,
|
||||
IPatientRepository patientRepository,
|
||||
IDoctorRepository doctorRepository)
|
||||
{
|
||||
public async Task<BaseResponse> Handle(AppointmentInformation request, CancellationToken token)
|
||||
{
|
||||
var validation = new CreateAppointmentValidator(appointmentsMongoDbService,
|
||||
doctorRepository, patientRepository);
|
||||
var validationResult = await validation.ValidateAsync(request, token);
|
||||
|
||||
if (!validationResult.IsValid)
|
||||
{
|
||||
var firstError = validationResult.Errors.FirstOrDefault();
|
||||
var errorCode = int.TryParse(firstError.ErrorCode, out var code) ? code : -1;
|
||||
var errorMessage = firstError.ErrorMessage;
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = errorCode,
|
||||
Message = errorMessage,
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
var appointmentId = IdentifierGenerator.GenerateId(request.DoctorId, request.PatientId);
|
||||
var criteria = new List<(string FieldName, string Value)>
|
||||
{
|
||||
("_id", appointmentId)
|
||||
};
|
||||
var appointments = await appointmentsMongoDbService.FindAsync<Appointment>(criteria, token);
|
||||
|
||||
if (appointments.Count == 0)
|
||||
{
|
||||
var appointment = new Appointment();
|
||||
appointment.SetId(appointmentId);
|
||||
appointment.SetDoctorIid(request.DoctorId.ToString());
|
||||
appointment.SetPatientId(request.PatientId.ToString());
|
||||
appointment.AddAppointment(request.Appointment);
|
||||
|
||||
await appointmentsMongoDbService.AddAsync(appointment, token);
|
||||
}
|
||||
else
|
||||
{
|
||||
var appointment = appointments[0];
|
||||
appointment.AddAppointment(request.Appointment);
|
||||
await appointmentsMongoDbService.ModifyAsync("_id", appointmentId, appointment, token);
|
||||
}
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.Created,
|
||||
Message = "Appointment successfully created.",
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
}
|
||||
+10
-9
@@ -2,9 +2,9 @@
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
using FluentValidation;
|
||||
|
||||
namespace Application.Endpoints.Appointments;
|
||||
namespace Application.Endpoints.Appointments.CreateAppointment;
|
||||
|
||||
public class CreateAppointmentValidator : AbstractValidator<AppointmentManagementDto>
|
||||
public class CreateAppointmentValidator : AbstractValidator<AppointmentInformation>
|
||||
{
|
||||
private readonly IAppointmentsMongoDbService _appointmentsMongoDbService;
|
||||
private readonly IDoctorRepository _doctorRepository;
|
||||
@@ -28,7 +28,8 @@ public class CreateAppointmentValidator : AbstractValidator<AppointmentManagemen
|
||||
.WithErrorCode(HttpStatusCodes.BadRequest.ToString());
|
||||
|
||||
RuleFor(x => x)
|
||||
.MustAsync(IsAppointmentUnique).WithMessage("Appointment already in system.")
|
||||
.MustAsync(IsAppointmentUnique)
|
||||
.WithMessage("Appointment already in system.")
|
||||
.WithErrorCode(HttpStatusCodes.Conflict.ToString());
|
||||
|
||||
_appointmentsMongoDbService = appointmentsMongoDbService;
|
||||
@@ -36,15 +37,15 @@ public class CreateAppointmentValidator : AbstractValidator<AppointmentManagemen
|
||||
_patientRepository = patientRepository;
|
||||
}
|
||||
|
||||
private async Task<bool> IsDoctorRegistered(Guid id, CancellationToken cancellationToken)
|
||||
private async Task<bool> IsDoctorRegistered(Guid id, CancellationToken token)
|
||||
{
|
||||
var doctor = await _doctorRepository.GetByIdAsync(id);
|
||||
var doctor = await _doctorRepository.GetByIdAsync(id, token);
|
||||
return doctor != null;
|
||||
}
|
||||
|
||||
private async Task<bool> IsPatientRegistered(Guid id, CancellationToken cancellationToken)
|
||||
private async Task<bool> IsPatientRegistered(Guid id, CancellationToken token)
|
||||
{
|
||||
var patient = await _patientRepository.GetByIdAsync(id);
|
||||
var patient = await _patientRepository.GetByIdAsync(id, token);
|
||||
return patient != null;
|
||||
}
|
||||
|
||||
@@ -59,8 +60,8 @@ public class CreateAppointmentValidator : AbstractValidator<AppointmentManagemen
|
||||
return true;
|
||||
}
|
||||
|
||||
private async Task<bool> IsAppointmentUnique(AppointmentManagementDto dto, CancellationToken cancellationToken)
|
||||
private async Task<bool> IsAppointmentUnique(AppointmentInformation request, CancellationToken token)
|
||||
{
|
||||
return await _appointmentsMongoDbService.IsAppointmentUnique(dto);
|
||||
return await _appointmentsMongoDbService.IsAppointmentUnique(request, token);
|
||||
}
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
using Application.Services.Database.MongoDB;
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
using Domain.Entities;
|
||||
|
||||
namespace Application.Endpoints.Appointments.DeleteAppointment;
|
||||
|
||||
public class DeleteAppointmentHandler(
|
||||
IAppointmentsMongoDbService appointmentsMongoDbService,
|
||||
IPatientRepository patientRepository,
|
||||
IDoctorRepository doctorRepository)
|
||||
{
|
||||
public async Task<BaseResponse> Handle(AppointmentInformation request, CancellationToken token)
|
||||
{
|
||||
var validation = new DeleteAppointmentValidator(appointmentsMongoDbService,
|
||||
doctorRepository, patientRepository);
|
||||
var validationResult = await validation.ValidateAsync(request, token);
|
||||
|
||||
if (!validationResult.IsValid)
|
||||
{
|
||||
var firstError = validationResult.Errors.FirstOrDefault();
|
||||
var errorCode = int.TryParse(firstError.ErrorCode, out var code) ? code : -1;
|
||||
var errorMessage = firstError.ErrorMessage;
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = errorCode,
|
||||
Message = errorMessage,
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
var appointmentId = IdentifierGenerator.GenerateId(request.DoctorId, request.PatientId);
|
||||
var criteria = new List<(string FieldName, string Value)>
|
||||
{
|
||||
("_id", appointmentId)
|
||||
};
|
||||
var appointments = await appointmentsMongoDbService.FindAsync<Appointment>(criteria, token);
|
||||
|
||||
if (!appointments.Any())
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NotFound,
|
||||
Message = "Appointment not found in system.",
|
||||
Data = null
|
||||
};
|
||||
|
||||
var appointment = appointments[0];
|
||||
appointment.RemoveAppointment(request.Appointment);
|
||||
await appointmentsMongoDbService.ModifyAsync("_id", appointmentId, appointment, token);
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.OK,
|
||||
Message = "Appointment successfully removed.",
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
}
|
||||
+9
-8
@@ -1,10 +1,11 @@
|
||||
using Application.Services.Database.MongoDB;
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
using Domain.Entities;
|
||||
using FluentValidation;
|
||||
|
||||
namespace Application.Endpoints.Appointments;
|
||||
namespace Application.Endpoints.Appointments.DeleteAppointment;
|
||||
|
||||
public class DeleteAppointmentValidator : AbstractValidator<AppointmentManagementDto>
|
||||
public class DeleteAppointmentValidator : AbstractValidator<AppointmentInformation>
|
||||
{
|
||||
private readonly IAppointmentsMongoDbService _appointmentsMongoDbService;
|
||||
private readonly IDoctorRepository _doctorRepository;
|
||||
@@ -36,15 +37,15 @@ public class DeleteAppointmentValidator : AbstractValidator<AppointmentManagemen
|
||||
_patientRepository = patientRepository;
|
||||
}
|
||||
|
||||
private async Task<bool> IsDoctorRegistered(Guid id, CancellationToken cancellationToken)
|
||||
private async Task<bool> IsDoctorRegistered(Guid id, CancellationToken token)
|
||||
{
|
||||
var doctor = await _doctorRepository.GetByIdAsync(id);
|
||||
var doctor = await _doctorRepository.GetByIdAsync(id, token);
|
||||
return doctor != null;
|
||||
}
|
||||
|
||||
private async Task<bool> IsPatientRegistered(Guid id, CancellationToken cancellationToken)
|
||||
private async Task<bool> IsPatientRegistered(Guid id, CancellationToken token)
|
||||
{
|
||||
var patient = await _patientRepository.GetByIdAsync(id);
|
||||
var patient = await _patientRepository.GetByIdAsync(id, token);
|
||||
return patient != null;
|
||||
}
|
||||
|
||||
@@ -59,8 +60,8 @@ public class DeleteAppointmentValidator : AbstractValidator<AppointmentManagemen
|
||||
return true;
|
||||
}
|
||||
|
||||
private async Task<bool> DoesAppointmentExists(AppointmentManagementDto dto, CancellationToken cancellationToken)
|
||||
private async Task<bool> DoesAppointmentExists(AppointmentInformation request, CancellationToken token)
|
||||
{
|
||||
return await _appointmentsMongoDbService.DoesAppointmentExists(dto);
|
||||
return await _appointmentsMongoDbService.DoesAppointmentExists(request, token);
|
||||
}
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
using Application.Services.Database.MongoDB;
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
using Domain.Entities;
|
||||
|
||||
namespace Application.Endpoints.Appointments.QuerriesAppointments;
|
||||
|
||||
public class QuerriesAppointmentHandler(IAppointmentsMongoDbService appointmentsMongoDbService)
|
||||
{
|
||||
public async Task<BaseResponse> GetByPatientId(Guid patientId, CancellationToken token)
|
||||
{
|
||||
var criteria = new List<(string FieldName, string Value)>
|
||||
{
|
||||
("PatientId", patientId.ToString())
|
||||
};
|
||||
var appointments = await appointmentsMongoDbService.FindAsync<Appointment>(criteria, token);
|
||||
|
||||
if (appointments.Count == 0)
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NotFound,
|
||||
Message = $"Appointments not found in system.",
|
||||
Data = null
|
||||
};
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.OK,
|
||||
Message = $"Appointments successfully retrieved.",
|
||||
Data = appointments
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<BaseResponse> GetsByDoctorId(Guid doctorId, CancellationToken token)
|
||||
{
|
||||
var criteria = new List<(string FieldName, string Value)>
|
||||
{
|
||||
("DoctorId", doctorId.ToString())
|
||||
};
|
||||
var appointments = await appointmentsMongoDbService.FindAsync<Appointment>(criteria, token);
|
||||
|
||||
if (appointments.Count == 0)
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NotFound,
|
||||
Message = $"Appointments not found in system.",
|
||||
Data = null
|
||||
};
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.OK,
|
||||
Message = $"Appointments successfully retrieved.",
|
||||
Data = appointments
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
using Application.Services.HashingAlgorithms;
|
||||
|
||||
namespace Application.Endpoints.Authorization.Doctor;
|
||||
|
||||
public class DoctorLoginHandler
|
||||
{
|
||||
private readonly IDoctorRepository _database;
|
||||
private readonly IHashingAlgorithms _hashingAlgorithms;
|
||||
|
||||
public DoctorLoginHandler(IDoctorRepository database, IHashingAlgorithms hashingAlgorithms)
|
||||
{
|
||||
_database = database;
|
||||
_hashingAlgorithms = hashingAlgorithms;
|
||||
}
|
||||
|
||||
public async Task<BaseResponse> Handle(LoginDto loginDTO)
|
||||
{
|
||||
loginDTO.Password = _hashingAlgorithms.SHA256Algorithm(loginDTO.Password);
|
||||
|
||||
var validation = new DoctorLoginValidation(_database);
|
||||
var validationResult = await validation.ValidateAsync(loginDTO);
|
||||
|
||||
if (validationResult.IsValid)
|
||||
{
|
||||
var doctor = await _database.FindByEmailAsync(loginDTO.Email);
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.OK,
|
||||
Message = "Authentication successful",
|
||||
Data = doctor
|
||||
};
|
||||
}
|
||||
|
||||
var firstError = validationResult.Errors.FirstOrDefault();
|
||||
var errorCode = int.TryParse(firstError.ErrorCode, out var code) ? code : -1;
|
||||
var errorMessage = firstError.ErrorMessage;
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = errorCode,
|
||||
Message = errorMessage,
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
using FluentValidation;
|
||||
|
||||
namespace Application.Endpoints.Authorization.Doctor;
|
||||
|
||||
public class DoctorLoginValidation : AbstractValidator<LoginDto>
|
||||
{
|
||||
private readonly IDoctorRepository _doctorRepository;
|
||||
|
||||
public DoctorLoginValidation(IDoctorRepository doctorRepository)
|
||||
{
|
||||
_doctorRepository = doctorRepository;
|
||||
|
||||
RuleFor(x => x.Email)
|
||||
.NotEmpty().WithMessage("Email is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString())
|
||||
.EmailAddress().WithMessage("Invalid email format.").WithErrorCode(HttpStatusCodes.BadRequest.ToString());
|
||||
|
||||
RuleFor(x => x.Password)
|
||||
.NotEmpty().WithMessage("Password is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString())
|
||||
.MinimumLength(8).WithMessage("Password must be at least 8 characters long.")
|
||||
.WithErrorCode(HttpStatusCodes.BadRequest.ToString());
|
||||
|
||||
RuleFor(x => x)
|
||||
.MustAsync(CredentialsMatch).WithMessage("Invalid credentials")
|
||||
.WithErrorCode(HttpStatusCodes.Unauthorized.ToString());
|
||||
}
|
||||
|
||||
private async Task<bool> CredentialsMatch(LoginDto dto, CancellationToken cancellationToken)
|
||||
{
|
||||
var code = await _doctorRepository.CredentialsMatch(dto.Email, dto.Password);
|
||||
return code;
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
using Application.Services.HashingAlgorithms;
|
||||
|
||||
namespace Application.Endpoints.Authorization.Doctor;
|
||||
|
||||
public class DoctorResetPasswordHandler
|
||||
{
|
||||
private readonly IDoctorRepository _doctorRepository;
|
||||
private readonly IHashingAlgorithms _hashingAlgorithms;
|
||||
|
||||
public DoctorResetPasswordHandler(IDoctorRepository doctorRepository, IHashingAlgorithms hashingAlgorithms)
|
||||
{
|
||||
_doctorRepository = doctorRepository;
|
||||
_hashingAlgorithms = hashingAlgorithms;
|
||||
}
|
||||
|
||||
public async Task<BaseResponse> Handle(LoginDto resetDoctorDto)
|
||||
{
|
||||
var validation = new DoctorResetPasswordValidation(_doctorRepository, _hashingAlgorithms);
|
||||
var validationResult = await validation.ValidateAsync(resetDoctorDto);
|
||||
|
||||
if (!validationResult.IsValid)
|
||||
{
|
||||
var firstError = validationResult.Errors.FirstOrDefault();
|
||||
var errorCode = int.TryParse(firstError.ErrorCode, out var code) ? code : -1;
|
||||
var errorMessage = firstError.ErrorMessage;
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = errorCode,
|
||||
Message = errorMessage,
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
var currentDoctor = await _doctorRepository.FindByEmailAsync(resetDoctorDto.Email);
|
||||
var updatedDoctor = currentDoctor;
|
||||
updatedDoctor.SetPassword(_hashingAlgorithms.SHA256Algorithm(resetDoctorDto.Password));
|
||||
|
||||
await _doctorRepository.UpdateAsync(updatedDoctor);
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.OK,
|
||||
Message = "Password successfully changed!",
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
using System.Net;
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
using Application.Services.HashingAlgorithms;
|
||||
using FluentValidation;
|
||||
|
||||
namespace Application.Endpoints.Authorization.Doctor;
|
||||
|
||||
public class DoctorResetPasswordValidation : AbstractValidator<LoginDto>
|
||||
{
|
||||
private readonly IDoctorRepository _doctorRepository;
|
||||
private readonly IHashingAlgorithms _hashingAlgorithms;
|
||||
|
||||
public DoctorResetPasswordValidation(IDoctorRepository doctorRepository, IHashingAlgorithms hashingAlgorithms)
|
||||
{
|
||||
_doctorRepository = doctorRepository;
|
||||
_hashingAlgorithms = hashingAlgorithms;
|
||||
|
||||
RuleFor(x => x.Email)
|
||||
.NotEmpty().WithMessage("Email is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString())
|
||||
.EmailAddress().WithMessage("Invalid email format.").WithErrorCode(HttpStatusCodes.BadRequest.ToString())
|
||||
.MustAsync(BeExistingDoctor).WithMessage("Patient with this email does not exist.")
|
||||
.WithErrorCode(HttpStatusCodes.NotFound.ToString());
|
||||
|
||||
RuleFor(x => x.Password)
|
||||
.NotEmpty().WithMessage("Password is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString())
|
||||
.WithErrorCode(HttpStatusCode.BadRequest.ToString());
|
||||
|
||||
RuleFor(x => x)
|
||||
.MustAsync(BeDifferentFromOldPassword).WithMessage("Password can't be as the previous.")
|
||||
.WithErrorCode(HttpStatusCode.BadRequest.ToString()).WithErrorCode(HttpStatusCodes.BadRequest.ToString());
|
||||
}
|
||||
|
||||
private async Task<bool> BeExistingDoctor(string email, CancellationToken cancellationToken)
|
||||
{
|
||||
var doctor = await _doctorRepository.FindByEmailAsync(email);
|
||||
return doctor != null;
|
||||
}
|
||||
|
||||
private async Task<bool> BeDifferentFromOldPassword(LoginDto dto, CancellationToken cancellationToken)
|
||||
{
|
||||
var currentPatient = await _doctorRepository.FindByEmailAsync(dto.Email);
|
||||
return !_hashingAlgorithms.SHA256Algorithm(dto.Password)
|
||||
.Equals(currentPatient?.Password, StringComparison.Ordinal);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace Application.Endpoints.Authorization;
|
||||
|
||||
public class LoginDto
|
||||
{
|
||||
public string Email;
|
||||
public string Password;
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
using Application.Services.HashingAlgorithms;
|
||||
|
||||
namespace Application.Endpoints.Authorization.Patient;
|
||||
|
||||
public class PatientLoginHandler
|
||||
{
|
||||
private readonly IPatientRepository _patientRepository;
|
||||
private readonly IHashingAlgorithms _hashingAlgorithms;
|
||||
|
||||
public PatientLoginHandler(IPatientRepository patientRepository, IHashingAlgorithms hashingAlgorithms)
|
||||
{
|
||||
_patientRepository = patientRepository;
|
||||
_hashingAlgorithms = hashingAlgorithms;
|
||||
}
|
||||
|
||||
public async Task<BaseResponse> Handle(LoginDto loginDTO)
|
||||
{
|
||||
var validation = new PatientLoginValidation(_patientRepository, _hashingAlgorithms);
|
||||
var validationResult = await validation.ValidateAsync(loginDTO);
|
||||
|
||||
if (validationResult.IsValid)
|
||||
{
|
||||
var patient = await _patientRepository.FindByEmailAsync(loginDTO.Email);
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.OK,
|
||||
Message = "Authentication successful",
|
||||
Data = patient
|
||||
};
|
||||
}
|
||||
|
||||
var firstError = validationResult.Errors.FirstOrDefault();
|
||||
var errorCode = int.TryParse(firstError.ErrorCode, out var code) ? code : -1;
|
||||
var errorMessage = firstError.ErrorMessage;
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = errorCode,
|
||||
Message = errorMessage,
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
using Application.Services.HashingAlgorithms;
|
||||
using FluentValidation;
|
||||
|
||||
namespace Application.Endpoints.Authorization.Patient;
|
||||
|
||||
public class PatientLoginValidation : AbstractValidator<LoginDto>
|
||||
{
|
||||
private readonly IPatientRepository _patientRepository;
|
||||
private readonly IHashingAlgorithms _hashingAlgorithms;
|
||||
|
||||
public PatientLoginValidation(IPatientRepository patientRepository, IHashingAlgorithms hashingAlgorithms)
|
||||
{
|
||||
_patientRepository = patientRepository;
|
||||
_hashingAlgorithms = hashingAlgorithms;
|
||||
|
||||
RuleFor(x => x.Email)
|
||||
.NotEmpty().WithMessage("Email is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString())
|
||||
.EmailAddress().WithMessage("Invalid email format.").WithErrorCode(HttpStatusCodes.BadRequest.ToString());
|
||||
|
||||
RuleFor(x => x.Password)
|
||||
.NotEmpty().WithMessage("Password is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString())
|
||||
.MinimumLength(8).WithMessage("Password must be at least 8 characters long.")
|
||||
.WithErrorCode(HttpStatusCodes.BadRequest.ToString());
|
||||
|
||||
RuleFor(x => x)
|
||||
.MustAsync(CredentialsMatch).WithMessage("Invalid credentials")
|
||||
.WithErrorCode(HttpStatusCodes.Unauthorized.ToString());
|
||||
}
|
||||
|
||||
private async Task<bool> CredentialsMatch(LoginDto dto, CancellationToken cancellationToken)
|
||||
{
|
||||
var code = await _patientRepository.CredentialsMatch(
|
||||
dto.Email, _hashingAlgorithms.SHA256Algorithm(dto.Password));
|
||||
return code;
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
using Application.Services.HashingAlgorithms;
|
||||
|
||||
namespace Application.Endpoints.Authorization.Patient;
|
||||
|
||||
public class PatientResetPasswordHandler
|
||||
{
|
||||
private readonly IHashingAlgorithms _hashingAlgorithms;
|
||||
private readonly IPatientRepository _patientRepository;
|
||||
|
||||
public PatientResetPasswordHandler(IPatientRepository patientRepository, IHashingAlgorithms hashingAlgorithms)
|
||||
{
|
||||
_patientRepository = patientRepository;
|
||||
_hashingAlgorithms = hashingAlgorithms;
|
||||
}
|
||||
|
||||
public async Task<BaseResponse> Handle(LoginDto patientResetPasswordDto)
|
||||
{
|
||||
var validation = new PatientResetPasswordValidation(_patientRepository, _hashingAlgorithms);
|
||||
var validationResult = await validation.ValidateAsync(patientResetPasswordDto);
|
||||
|
||||
if (!validationResult.IsValid)
|
||||
{
|
||||
var firstError = validationResult.Errors.FirstOrDefault();
|
||||
var errorCode = int.TryParse(firstError.ErrorCode, out var code) ? code : -1;
|
||||
var errorMessage = firstError.ErrorMessage;
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = errorCode,
|
||||
Message = errorMessage,
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
var currentPatient = await _patientRepository.FindByEmailAsync(patientResetPasswordDto.Email);
|
||||
var updatedPatient = currentPatient;
|
||||
updatedPatient.SetPassword(_hashingAlgorithms.SHA256Algorithm(patientResetPasswordDto.Password));
|
||||
|
||||
await _patientRepository.UpdateAsync(updatedPatient);
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.OK,
|
||||
Message = "Password successfully changed!",
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
using System.Net;
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
using Application.Services.HashingAlgorithms;
|
||||
using FluentValidation;
|
||||
|
||||
namespace Application.Endpoints.Authorization.Patient;
|
||||
|
||||
public class PatientResetPasswordValidation : AbstractValidator<LoginDto>
|
||||
{
|
||||
private readonly IPatientRepository _patientRepository;
|
||||
private readonly IHashingAlgorithms _hashingAlgorithms;
|
||||
|
||||
public PatientResetPasswordValidation(IPatientRepository patientRepository,
|
||||
IHashingAlgorithms hashingAlgorithms)
|
||||
{
|
||||
_patientRepository = patientRepository;
|
||||
_hashingAlgorithms = hashingAlgorithms;
|
||||
|
||||
RuleFor(x => x.Email)
|
||||
.NotEmpty().WithMessage("Email is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString())
|
||||
.EmailAddress().WithMessage("Invalid email format.").WithErrorCode(HttpStatusCodes.BadRequest.ToString())
|
||||
.MustAsync(BeExistingPatient).WithMessage("Patient with this email does not exist.")
|
||||
.WithErrorCode(HttpStatusCodes.NotFound.ToString());
|
||||
|
||||
RuleFor(x => x.Password)
|
||||
.NotEmpty().WithMessage("Password is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString())
|
||||
.WithErrorCode(HttpStatusCode.BadRequest.ToString());
|
||||
|
||||
RuleFor(x => x)
|
||||
.MustAsync(BeDifferentFromOldPassword).WithMessage("Password can't be as the previous.")
|
||||
.WithErrorCode(HttpStatusCode.BadRequest.ToString()).WithErrorCode(HttpStatusCodes.BadRequest.ToString());
|
||||
}
|
||||
|
||||
private async Task<bool> BeExistingPatient(string email, CancellationToken cancellationToken)
|
||||
{
|
||||
var patient = await _patientRepository.FindByEmailAsync(email);
|
||||
return patient != null;
|
||||
}
|
||||
|
||||
private async Task<bool> BeDifferentFromOldPassword(LoginDto dto, CancellationToken cancellationToken)
|
||||
{
|
||||
var currentPatient = await _patientRepository.FindByEmailAsync(dto.Email);
|
||||
return !_hashingAlgorithms.SHA256Algorithm(dto.Password)
|
||||
.Equals(currentPatient?.Password, StringComparison.Ordinal);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Application.Endpoints.Authorization.RefreshToken;
|
||||
|
||||
public class RefreshJwtCommand
|
||||
{
|
||||
public string Token { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using Application.Services.Jwt;
|
||||
|
||||
namespace Application.Endpoints.Authorization.RefreshToken;
|
||||
|
||||
public class RefreshJwtHandler(IJwtService jwtService)
|
||||
{
|
||||
public async Task<BaseResponse> Handle(RefreshJwtCommand command, CancellationToken cancellationToken)
|
||||
{
|
||||
var validator = new RefreshJwtValidator(jwtService);
|
||||
var validationResult = await validator.ValidateAsync(command, cancellationToken);
|
||||
|
||||
if (!validationResult.IsValid)
|
||||
{
|
||||
var firstError = validationResult.Errors.FirstOrDefault();
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.Unauthorized,
|
||||
Message = firstError?.ErrorMessage
|
||||
};
|
||||
}
|
||||
|
||||
var newToken = jwtService.RefreshToken(command.Token);
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.OK,
|
||||
Message = "Token refreshed successfully.",
|
||||
Data = newToken
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using Application.Services.Jwt;
|
||||
using FluentValidation;
|
||||
|
||||
namespace Application.Endpoints.Authorization.RefreshToken;
|
||||
|
||||
public class RefreshJwtValidator : AbstractValidator<RefreshJwtCommand>
|
||||
{
|
||||
private readonly IJwtService _jwtService;
|
||||
|
||||
public RefreshJwtValidator(IJwtService jwtService)
|
||||
{
|
||||
_jwtService = jwtService;
|
||||
|
||||
RuleFor(x => x.Token)
|
||||
.NotEmpty().WithMessage("Token is required.")
|
||||
.Must(BeAValidToken).WithMessage("Token is invalid or expired.");
|
||||
}
|
||||
|
||||
private bool BeAValidToken(string token)
|
||||
{
|
||||
return _jwtService.ValidateJwtToken(token);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Application.Endpoints.Authorization.UserLogin;
|
||||
|
||||
public class UserLoginCommand
|
||||
{
|
||||
public string Email { get; set; } = string.Empty;
|
||||
public string Password { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
using Application.Services.HashingAlgorithms;
|
||||
using Application.Services.Jwt;
|
||||
using Domain;
|
||||
|
||||
namespace Application.Endpoints.Authorization.UserLogin;
|
||||
|
||||
public class UserLoginHandler(
|
||||
IJwtService jwtService,
|
||||
IHashingAlgorithms hashingAlgorithms,
|
||||
IDoctorRepository doctorRepository,
|
||||
IPatientRepository patientRepository,
|
||||
IAdminRepository adminRepository)
|
||||
{
|
||||
public async Task<BaseResponse> Handle(UserLoginCommand request, CancellationToken token)
|
||||
{
|
||||
var validator = new UserLoginValidator();
|
||||
var result = await validator.ValidateAsync(request, token);
|
||||
if (!result.IsValid)
|
||||
{
|
||||
var firstError = result.Errors.FirstOrDefault();
|
||||
var errorCode = int.TryParse(firstError.ErrorCode, out var code) ? code : -1;
|
||||
var errorMessage = firstError.ErrorMessage;
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = errorCode,
|
||||
Message = errorMessage,
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
var email = request.Email;
|
||||
var password = hashingAlgorithms.Sha256Algorithm(request.Password);
|
||||
|
||||
if (await doctorRepository.CredentialsMatch(email, password, token))
|
||||
{
|
||||
var doctor = await doctorRepository.FindByEmailAsync(email, token);
|
||||
var authToken = jwtService.GenerateJwtToken(doctor.Id, UserRoles.Doctor, doctor.Name);
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.OK,
|
||||
Message = "Doctor logged in successfully.",
|
||||
Data = authToken
|
||||
};
|
||||
}
|
||||
|
||||
if (await patientRepository.CredentialsMatch(email, password, token))
|
||||
{
|
||||
var patient = await patientRepository.FindByEmailAsync(email, token);
|
||||
var authToken = jwtService.GenerateJwtToken(patient.Id, UserRoles.Patient, patient.Name);
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.OK,
|
||||
Message = "Patient logged in successfully.",
|
||||
Data = authToken
|
||||
};
|
||||
}
|
||||
|
||||
if (await adminRepository.CredentialsMatch(email, password, token))
|
||||
{
|
||||
var admin = await adminRepository.FindByEmailAsync(email, token);
|
||||
var authToken = jwtService.GenerateJwtToken(admin.Id, UserRoles.Admin, admin.Name);
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.OK,
|
||||
Message = "Admin logged in successfully.",
|
||||
Data = authToken
|
||||
};
|
||||
}
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NotFound,
|
||||
Message = "User not registered in our system.",
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using FluentValidation;
|
||||
|
||||
namespace Application.Endpoints.Authorization.UserLogin;
|
||||
|
||||
public class UserLoginValidator : AbstractValidator<UserLoginCommand>
|
||||
{
|
||||
public UserLoginValidator()
|
||||
{
|
||||
RuleFor(x => x.Email)
|
||||
.NotEmpty().WithMessage("Email is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString())
|
||||
.EmailAddress().WithMessage("Invalid email format.").WithErrorCode(HttpStatusCodes.BadRequest.ToString());
|
||||
|
||||
RuleFor(x => x.Password)
|
||||
.NotEmpty().WithMessage("Password is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString())
|
||||
.MinimumLength(8).WithMessage("Password must be at least 8 characters long.")
|
||||
.WithErrorCode(HttpStatusCodes.BadRequest.ToString());
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
namespace Application.Endpoints.Authorization;
|
||||
|
||||
public class UserLoginModel
|
||||
{
|
||||
public string? UserType { get; set; }
|
||||
public string Email { get; set; }
|
||||
public string Password { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Application.Endpoints.Authorization.UserRegister;
|
||||
|
||||
public class UserRegisterCommand
|
||||
{
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public string Email { get; set; } = string.Empty;
|
||||
public string Password { get; set; } = string.Empty;
|
||||
public string Role { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
using Application.Services.Email;
|
||||
using Application.Services.HashingAlgorithms;
|
||||
using Domain;
|
||||
using Domain.Entities;
|
||||
|
||||
namespace Application.Endpoints.Authorization.UserRegister;
|
||||
|
||||
public class UserRegisterHandler(
|
||||
IEmailService emailService,
|
||||
IHashingAlgorithms hashingAlgorithms,
|
||||
IDoctorRepository doctorRepository,
|
||||
IPatientRepository patientRepository,
|
||||
IAdminRepository adminRepository)
|
||||
{
|
||||
public async Task<BaseResponse> Handle(UserRegisterCommand request, CancellationToken token)
|
||||
{
|
||||
var validator = new UserRegisterValidator(
|
||||
patientRepository, doctorRepository, adminRepository);
|
||||
var result = await validator.ValidateAsync(request, token);
|
||||
if (!result.IsValid)
|
||||
{
|
||||
var firstError = result.Errors.FirstOrDefault();
|
||||
var errorCode = int.TryParse(firstError.ErrorCode, out var code) ? code : -1;
|
||||
var errorMessage = firstError.ErrorMessage;
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = errorCode,
|
||||
Message = errorMessage,
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
switch (request.Role)
|
||||
{
|
||||
case UserRoles.Admin:
|
||||
var admin = new Admin();
|
||||
admin.SetName(request.Name);
|
||||
admin.SetEmail(request.Email);
|
||||
admin.SetPassword(hashingAlgorithms.Sha256Algorithm(request.Password));
|
||||
|
||||
await adminRepository.AddAsync(admin, token);
|
||||
break;
|
||||
case UserRoles.Doctor:
|
||||
var doctor = new Doctor();
|
||||
doctor.SetName(request.Name);
|
||||
doctor.SetEmail(request.Email);
|
||||
doctor.SetPassword(hashingAlgorithms.Sha256Algorithm(request.Password));
|
||||
|
||||
await doctorRepository.AddAsync(doctor, token);
|
||||
break;
|
||||
case UserRoles.Patient:
|
||||
var patient = new Patient();
|
||||
patient.SetName(request.Name);
|
||||
patient.SetEmail(request.Email);
|
||||
patient.SetPassword(hashingAlgorithms.Sha256Algorithm(request.Password));
|
||||
|
||||
await patientRepository.AddAsync(patient, token);
|
||||
break;
|
||||
}
|
||||
|
||||
var emailBody = emailService.GenerateCredentialsEmailBody(request.Name, request.Email, request.Password);
|
||||
await emailService.SendEmailAsync(request.Email, emailService.GetSuccessfulRegistrationSubject(), emailBody);
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.Created,
|
||||
Message = "User created successfully",
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
using Application.Services.HashingAlgorithms;
|
||||
using Domain;
|
||||
using FluentValidation;
|
||||
|
||||
namespace Application.Endpoints.Authorization.UserRegister;
|
||||
|
||||
public class UserRegisterValidator : AbstractValidator<UserRegisterCommand>
|
||||
{
|
||||
private readonly IAdminRepository _adminRepository;
|
||||
private readonly IDoctorRepository _doctorRepository;
|
||||
private readonly IPatientRepository _patientRepository;
|
||||
|
||||
public UserRegisterValidator(IPatientRepository patientRepository,
|
||||
IDoctorRepository doctorRepository, IAdminRepository adminRepository)
|
||||
{
|
||||
_patientRepository = patientRepository;
|
||||
_doctorRepository = doctorRepository;
|
||||
_adminRepository = adminRepository;
|
||||
|
||||
RuleFor(x => x.Name)
|
||||
.NotEmpty().WithMessage("Name is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString())
|
||||
.MaximumLength(30).WithMessage("Maximum name length of 30 characters")
|
||||
.WithErrorCode(HttpStatusCodes.BadRequest.ToString());
|
||||
|
||||
RuleFor(x => x.Email)
|
||||
.NotEmpty().WithMessage("Email is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString())
|
||||
.EmailAddress().WithMessage("Invalid email format.").WithErrorCode(HttpStatusCodes.BadRequest.ToString())
|
||||
.MustAsync(async (email, token) => await AccountNotRegistered(email, token))
|
||||
.WithMessage("Account already registered in system.").WithErrorCode(HttpStatusCodes.BadRequest.ToString());
|
||||
|
||||
RuleFor(x => x.Password)
|
||||
.NotEmpty().WithMessage("Password is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString())
|
||||
.MinimumLength(8).WithMessage("Password must be at least 8 characters long.")
|
||||
.WithErrorCode(HttpStatusCodes.BadRequest.ToString());
|
||||
|
||||
RuleFor(x => x.Role)
|
||||
.NotEmpty().WithMessage("Role is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString())
|
||||
.Must(BeAValidRole).WithMessage("Invalid role specified.")
|
||||
.WithErrorCode(HttpStatusCodes.BadRequest.ToString());
|
||||
}
|
||||
|
||||
private bool BeAValidRole(string role)
|
||||
{
|
||||
var validRoles = new[] { UserRoles.Admin, UserRoles.Doctor, UserRoles.Patient };
|
||||
return validRoles.Contains(role);
|
||||
}
|
||||
|
||||
private async Task<bool> AccountNotRegistered(string email, CancellationToken token)
|
||||
{
|
||||
var patient = await _patientRepository.FindByEmailAsync(email, token);
|
||||
var doctor = await _doctorRepository.FindByEmailAsync(email, token);
|
||||
var admin = await _adminRepository.FindByEmailAsync(email, token);
|
||||
|
||||
return patient == null && doctor == null && admin == null;
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
namespace Application.Endpoints.Authorization.UserResetPassword;
|
||||
|
||||
public class UserResetPasswordCommand
|
||||
{
|
||||
public string Email { get; set; } = string.Empty;
|
||||
public string Password { get; set; } = string.Empty;
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
using Application.Services.Email;
|
||||
using Application.Services.HashingAlgorithms;
|
||||
|
||||
namespace Application.Endpoints.Authorization.UserResetPassword;
|
||||
|
||||
public class UserResetPasswordHandler(
|
||||
IEmailService emailService,
|
||||
IHashingAlgorithms hashingAlgorithms,
|
||||
IDoctorRepository doctorRepository,
|
||||
IPatientRepository patientRepository,
|
||||
IAdminRepository adminRepository)
|
||||
{
|
||||
public async Task<BaseResponse> Handle(UserResetPasswordCommand request, CancellationToken token)
|
||||
{
|
||||
var validator = new UserResetPasswordValidator(
|
||||
patientRepository, doctorRepository, adminRepository);
|
||||
var result = await validator.ValidateAsync(request, token);
|
||||
if (!result.IsValid)
|
||||
{
|
||||
var firstError = result.Errors.FirstOrDefault();
|
||||
var errorCode = int.TryParse(firstError.ErrorCode, out var code) ? code : -1;
|
||||
var errorMessage = firstError.ErrorMessage;
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = errorCode,
|
||||
Message = errorMessage,
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
string? name = null;
|
||||
var patient = await patientRepository.FindByEmailAsync(request.Email, token);
|
||||
if (patient != null)
|
||||
{
|
||||
name = patient.Name;
|
||||
patient.SetPassword(hashingAlgorithms.Sha256Algorithm(request.Password));
|
||||
await patientRepository.UpdateAsync(patient, token);
|
||||
}
|
||||
|
||||
var doctor = await doctorRepository.FindByEmailAsync(request.Email, token);
|
||||
if (doctor != null)
|
||||
{
|
||||
name = doctor.Name;
|
||||
doctor.SetPassword(hashingAlgorithms.Sha256Algorithm(request.Password));
|
||||
await doctorRepository.UpdateAsync(doctor, token);
|
||||
}
|
||||
|
||||
var admin = await adminRepository.FindByEmailAsync(request.Email, token);
|
||||
if (admin != null)
|
||||
{
|
||||
name = admin.Name;
|
||||
admin.SetPassword(hashingAlgorithms.Sha256Algorithm(request.Password));
|
||||
await adminRepository.UpdateAsync(admin, token);
|
||||
}
|
||||
|
||||
var emailBody = emailService.GenerateResetCredentialsEmailBody(name, request.Email, request.Password);
|
||||
await emailService.SendEmailAsync(request.Email, emailService.GetSuccessfulPasswordResetSubject(), emailBody);
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.OK,
|
||||
Message = "Password updated successfully.",
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
using Domain;
|
||||
using FluentValidation;
|
||||
|
||||
namespace Application.Endpoints.Authorization.UserResetPassword;
|
||||
|
||||
public class UserResetPasswordValidator : AbstractValidator<UserResetPasswordCommand>
|
||||
{
|
||||
private readonly IAdminRepository _adminRepository;
|
||||
private readonly IDoctorRepository _doctorRepository;
|
||||
private readonly IPatientRepository _patientRepository;
|
||||
|
||||
public UserResetPasswordValidator(IPatientRepository patientRepository,
|
||||
IDoctorRepository doctorRepository, IAdminRepository adminRepository)
|
||||
{
|
||||
_patientRepository = patientRepository;
|
||||
_doctorRepository = doctorRepository;
|
||||
_adminRepository = adminRepository;
|
||||
|
||||
RuleFor(x => x.Email)
|
||||
.NotEmpty().WithMessage("Email is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString())
|
||||
.EmailAddress().WithMessage("Invalid email format.").WithErrorCode(HttpStatusCodes.BadRequest.ToString())
|
||||
.MustAsync(async (email, token) => await AccountRegistered(email, token))
|
||||
.WithMessage("Account already registered in system.").WithErrorCode(HttpStatusCodes.BadRequest.ToString());
|
||||
|
||||
|
||||
RuleFor(x => x.Password)
|
||||
.NotEmpty().WithMessage("Password is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString())
|
||||
.MinimumLength(8).WithMessage("Password must be at least 8 characters long.")
|
||||
.WithErrorCode(HttpStatusCodes.BadRequest.ToString());
|
||||
|
||||
RuleFor(x => x)
|
||||
.MustAsync(async (request, token) =>
|
||||
await AccountRegistered(request.Email, token))
|
||||
.WithMessage("Account already registered in system.").WithErrorCode(HttpStatusCodes.BadRequest.ToString());
|
||||
}
|
||||
|
||||
private bool BeAValidRole(string role)
|
||||
{
|
||||
var validRoles = new[] { UserRoles.Admin, UserRoles.Doctor, UserRoles.Patient };
|
||||
return validRoles.Contains(role);
|
||||
}
|
||||
|
||||
private async Task<bool> AccountRegistered(string email, CancellationToken token)
|
||||
{
|
||||
var patient = await _patientRepository.FindByEmailAsync(email, token);
|
||||
var doctor = await _doctorRepository.FindByEmailAsync(email, token);
|
||||
var admin = await _adminRepository.FindByEmailAsync(email, token);
|
||||
|
||||
return patient != null || doctor != null || admin != null;
|
||||
}
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
using Application.Services.Database.MongoDB;
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
using Core.Entities;
|
||||
|
||||
namespace Application.Endpoints.Chats;
|
||||
|
||||
public class ChatHandler
|
||||
{
|
||||
private readonly IChatMongoDbService _chatMongoDbService;
|
||||
private readonly IDoctorRepository _doctorRepository;
|
||||
private readonly IPatientRepository _patientRepository;
|
||||
|
||||
public ChatHandler(IChatMongoDbService chatMongoDbService, IPatientRepository patientRepository,
|
||||
IDoctorRepository doctorRepository)
|
||||
{
|
||||
_chatMongoDbService = chatMongoDbService;
|
||||
_patientRepository = patientRepository;
|
||||
_doctorRepository = doctorRepository;
|
||||
}
|
||||
|
||||
public async Task<BaseResponse> HandleSendMessage(SendMessageDto sendMessageDto)
|
||||
{
|
||||
var validation = new SendMessageValidator();
|
||||
var validationResult = await validation.ValidateAsync(sendMessageDto);
|
||||
|
||||
if (!validationResult.IsValid)
|
||||
{
|
||||
var firstError = validationResult.Errors.FirstOrDefault();
|
||||
var errorCode = int.TryParse(firstError.ErrorCode, out var code) ? code : -1;
|
||||
var errorMessage = firstError.ErrorMessage;
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = errorCode,
|
||||
Message = errorMessage,
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
if (!await CheckForUsersExistence(sendMessageDto.Sender, sendMessageDto.Receiver))
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.BadRequest,
|
||||
Message = "Users can't be found in the system.",
|
||||
Data = null
|
||||
};
|
||||
|
||||
var chatId = IdentifierGenerator.GenerateId(sendMessageDto.Sender, sendMessageDto.Receiver);
|
||||
|
||||
var criteria = new List<(string, string)>();
|
||||
criteria.Add(("_id", chatId));
|
||||
|
||||
var documents = await _chatMongoDbService.FindAsync<Chat>(criteria);
|
||||
if (!documents.Any())
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NotFound,
|
||||
Message = "Access to medical history not found.",
|
||||
Data = null
|
||||
};
|
||||
|
||||
var chat = documents[0].Messages;
|
||||
chat.Add(new Message(sendMessageDto.Sender, sendMessageDto.Message));
|
||||
|
||||
var newChat = new Chat();
|
||||
newChat.SetId(chatId);
|
||||
newChat.SetMessages(chat);
|
||||
|
||||
await _chatMongoDbService.ModifyAsync("_id", chatId, newChat);
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NoContent,
|
||||
Message = null,
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<BaseResponse> HandleGetConversation(GetConversationDto getConversationDto)
|
||||
{
|
||||
var validation = new GetConversationValidator();
|
||||
var validationResult = await validation.ValidateAsync(getConversationDto);
|
||||
|
||||
if (!validationResult.IsValid)
|
||||
{
|
||||
var firstError = validationResult.Errors.FirstOrDefault();
|
||||
var errorCode = int.TryParse(firstError.ErrorCode, out var code) ? code : -1;
|
||||
var errorMessage = firstError.ErrorMessage;
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = errorCode,
|
||||
Message = errorMessage,
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
if (!await CheckForUsersExistence(getConversationDto.IdUser1, getConversationDto.IdUser2))
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.BadRequest,
|
||||
Message = "Users can't be found in the system.",
|
||||
Data = null
|
||||
};
|
||||
|
||||
var chatId = IdentifierGenerator.GenerateId(getConversationDto.IdUser1, getConversationDto.IdUser2);
|
||||
|
||||
var criteria = new List<(string, string)>();
|
||||
criteria.Add(("_id", chatId));
|
||||
|
||||
Chat? chat = null;
|
||||
|
||||
var documents = await _chatMongoDbService.FindAsync<Chat>(criteria);
|
||||
if (!documents.Any())
|
||||
{
|
||||
chat = new Chat();
|
||||
chat.SetId(chatId);
|
||||
|
||||
await _chatMongoDbService.AddAsync(chat);
|
||||
}
|
||||
else
|
||||
{
|
||||
chat = documents[0];
|
||||
}
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.OK,
|
||||
Message = "Fetching messages.",
|
||||
Data = chat
|
||||
};
|
||||
}
|
||||
|
||||
private async Task<bool> CheckForUsersExistence(Guid idUser1, Guid idUser2)
|
||||
{
|
||||
var firstCheck = await _patientRepository.GetByIdAsync(idUser1) != null &&
|
||||
await _doctorRepository.GetByIdAsync(idUser2) != null;
|
||||
|
||||
var secondCheck = await _patientRepository.GetByIdAsync(idUser2) != null &&
|
||||
await _doctorRepository.GetByIdAsync(idUser1) != null;
|
||||
|
||||
return firstCheck || secondCheck;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Application.Endpoints.Chats.GetChats;
|
||||
|
||||
public class GetConversationsCommand
|
||||
{
|
||||
public Guid IdUser1 { get; set; } = Guid.Empty;
|
||||
public Guid IdUser2 { get; set; } = Guid.Empty;
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
using Application.Services.Database.MongoDB;
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
using Domain.Entities;
|
||||
|
||||
namespace Application.Endpoints.Chats.GetChats;
|
||||
|
||||
public class GetConversationsHandler(
|
||||
IChatMongoDbService chatMongoDbService,
|
||||
IPatientRepository patientRepository,
|
||||
IDoctorRepository doctorRepository)
|
||||
{
|
||||
public async Task<BaseResponse> HandleGetConversation(GetConversationsCommand getConversationCommand,
|
||||
CancellationToken token)
|
||||
{
|
||||
var validation = new GetConversationsValidator(doctorRepository, patientRepository);
|
||||
var validationResult = await validation.ValidateAsync(getConversationCommand, token);
|
||||
|
||||
if (!validationResult.IsValid)
|
||||
{
|
||||
var firstError = validationResult.Errors.FirstOrDefault();
|
||||
var errorCode = int.TryParse(firstError.ErrorCode, out var code) ? code : -1;
|
||||
var errorMessage = firstError.ErrorMessage;
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = errorCode,
|
||||
Message = errorMessage,
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
var chatId = IdentifierGenerator.GenerateId(getConversationCommand.IdUser1, getConversationCommand.IdUser2);
|
||||
|
||||
var criteria = new List<(string, string)>();
|
||||
criteria.Add(("_id", chatId));
|
||||
|
||||
Chat? chat = null;
|
||||
|
||||
var documents = await chatMongoDbService.FindAsync<Chat>(criteria, token);
|
||||
if (!documents.Any())
|
||||
{
|
||||
chat = new Chat();
|
||||
chat.SetId(chatId);
|
||||
|
||||
await chatMongoDbService.AddAsync(chat, token);
|
||||
}
|
||||
else
|
||||
{
|
||||
chat = documents[0];
|
||||
}
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.OK,
|
||||
Message = "Fetching messages.",
|
||||
Data = chat
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
using FluentValidation;
|
||||
|
||||
namespace Application.Endpoints.Chats.GetChats;
|
||||
|
||||
public class GetConversationsValidator : AbstractValidator<GetConversationsCommand>
|
||||
{
|
||||
private readonly IPatientRepository _patientRepository;
|
||||
private readonly IDoctorRepository _doctorRepository;
|
||||
|
||||
public GetConversationsValidator(IDoctorRepository doctorRepository, IPatientRepository patientRepository)
|
||||
{
|
||||
RuleFor(x => x.IdUser1)
|
||||
.NotEmpty().WithMessage("IdUser1 is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString());
|
||||
|
||||
RuleFor(x => x.IdUser2)
|
||||
.NotEmpty().WithMessage("IdUser2 is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString());
|
||||
|
||||
RuleFor(x => x)
|
||||
.MustAsync(CheckForUsersExistence).WithMessage("One of the users is not existing.")
|
||||
.WithErrorCode(HttpStatusCodes.BadRequest.ToString());
|
||||
|
||||
_patientRepository = patientRepository;
|
||||
_doctorRepository = doctorRepository;
|
||||
}
|
||||
|
||||
private async Task<bool> CheckForUsersExistence(GetConversationsCommand request, CancellationToken token)
|
||||
{
|
||||
var firstCheck = await _patientRepository.GetByIdAsync(request.IdUser1, token) != null &&
|
||||
await _doctorRepository.GetByIdAsync(request.IdUser2, token) != null;
|
||||
|
||||
var secondCheck = await _patientRepository.GetByIdAsync(request.IdUser2, token) != null &&
|
||||
await _doctorRepository.GetByIdAsync(request.IdUser1, token) != null;
|
||||
|
||||
return firstCheck || secondCheck;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace Application.Endpoints.Chats;
|
||||
|
||||
public class GetConversationDto
|
||||
{
|
||||
public Guid IdUser1 { get; set; }
|
||||
public Guid IdUser2 { get; set; }
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
using FluentValidation;
|
||||
|
||||
namespace Application.Endpoints.Chats;
|
||||
|
||||
public class GetConversationValidator : AbstractValidator<GetConversationDto>
|
||||
{
|
||||
public GetConversationValidator()
|
||||
{
|
||||
RuleFor(x => x.IdUser1)
|
||||
.NotEmpty().WithMessage("IdUser1 is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString());
|
||||
|
||||
RuleFor(x => x.IdUser2)
|
||||
.NotEmpty().WithMessage("IdUser2 is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Application.Endpoints.Chats.SendMessage;
|
||||
|
||||
public class SendMessageCommand
|
||||
{
|
||||
public Guid Sender { get; set; } = Guid.Empty;
|
||||
public Guid Receiver { get; set; } = Guid.Empty;
|
||||
public string Message { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
using Application.Services.Database.MongoDB;
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
using Domain.Entities;
|
||||
|
||||
namespace Application.Endpoints.Chats.SendMessage;
|
||||
|
||||
public class SendMessageHandler(
|
||||
IChatMongoDbService chatMongoDbService,
|
||||
IPatientRepository patientRepository,
|
||||
IDoctorRepository doctorRepository)
|
||||
{
|
||||
public async Task<BaseResponse> Handle(SendMessageCommand request, CancellationToken token)
|
||||
{
|
||||
var validation = new SendMessageValidator(doctorRepository, patientRepository);
|
||||
var validationResult = await validation.ValidateAsync(request, token);
|
||||
|
||||
if (!validationResult.IsValid)
|
||||
{
|
||||
var firstError = validationResult.Errors.FirstOrDefault();
|
||||
var errorCode = int.TryParse(firstError.ErrorCode, out var code) ? code : -1;
|
||||
var errorMessage = firstError.ErrorMessage;
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = errorCode,
|
||||
Message = errorMessage,
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
var chatId = IdentifierGenerator.GenerateId(request.Sender, request.Receiver);
|
||||
|
||||
var criteria = new List<(string, string)>();
|
||||
criteria.Add(("_id", chatId));
|
||||
|
||||
var documents = await chatMongoDbService.FindAsync<Chat>(criteria, token);
|
||||
if (!documents.Any())
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NotFound,
|
||||
Message = "Access to medical history not found.",
|
||||
Data = null
|
||||
};
|
||||
|
||||
var chat = documents[0].Messages;
|
||||
chat.Add(new Message(request.Sender, request.Message));
|
||||
|
||||
var newChat = new Chat();
|
||||
newChat.SetId(chatId);
|
||||
newChat.SetMessages(chat);
|
||||
|
||||
await chatMongoDbService.ModifyAsync("_id", chatId, newChat, token);
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NoContent,
|
||||
Message = null,
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
using FluentValidation;
|
||||
|
||||
namespace Application.Endpoints.Chats.SendMessage;
|
||||
|
||||
public class SendMessageValidator : AbstractValidator<SendMessageCommand>
|
||||
{
|
||||
private readonly IDoctorRepository _doctorRepository;
|
||||
private readonly IPatientRepository _patientRepository;
|
||||
|
||||
public SendMessageValidator(IDoctorRepository doctorRepository, IPatientRepository patientRepository)
|
||||
{
|
||||
RuleFor(x => x.Sender)
|
||||
.NotEmpty().WithMessage("Sender Id is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString());
|
||||
|
||||
RuleFor(x => x.Receiver)
|
||||
.NotEmpty().WithMessage("Receiver Id is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString());
|
||||
|
||||
RuleFor(x => x.Message)
|
||||
.NotEmpty().WithMessage("Message is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString());
|
||||
|
||||
RuleFor(x => x)
|
||||
.MustAsync(CheckForUsersExistence).WithMessage("One of the users is not existing.")
|
||||
.WithErrorCode(HttpStatusCodes.BadRequest.ToString());
|
||||
|
||||
_patientRepository = patientRepository;
|
||||
_doctorRepository = doctorRepository;
|
||||
}
|
||||
|
||||
private async Task<bool> CheckForUsersExistence(SendMessageCommand request, CancellationToken token)
|
||||
{
|
||||
var firstCheck = await _patientRepository.GetByIdAsync(request.Sender, token) != null &&
|
||||
await _doctorRepository.GetByIdAsync(request.Receiver, token) != null;
|
||||
|
||||
var secondCheck = await _patientRepository.GetByIdAsync(request.Receiver, token) != null &&
|
||||
await _doctorRepository.GetByIdAsync(request.Sender, token) != null;
|
||||
|
||||
return firstCheck || secondCheck;
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
namespace Application.Endpoints.Chats;
|
||||
|
||||
public class SendMessageDto
|
||||
{
|
||||
public Guid Sender { get; set; }
|
||||
public Guid Receiver { get; set; }
|
||||
public string Message { get; set; }
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
using FluentValidation;
|
||||
|
||||
namespace Application.Endpoints.Chats;
|
||||
|
||||
public class SendMessageValidator : AbstractValidator<SendMessageDto>
|
||||
{
|
||||
public SendMessageValidator()
|
||||
{
|
||||
RuleFor(x => x.Sender)
|
||||
.NotEmpty().WithMessage("Sender Id is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString());
|
||||
|
||||
RuleFor(x => x.Receiver)
|
||||
.NotEmpty().WithMessage("Receiver Id is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString());
|
||||
|
||||
RuleFor(x => x.Message)
|
||||
.NotEmpty().WithMessage("Message is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
using Application.Services.Database.MongoDB;
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
using Domain.Entities;
|
||||
|
||||
namespace Application.Endpoints.Doctors.DeleteDoctor;
|
||||
|
||||
public class DeleteDoctorHandler(
|
||||
IDoctorRepository doctorRepository,
|
||||
IAppointmentsMongoDbService appointmentsMongoDbService)
|
||||
{
|
||||
public async Task<BaseResponse> Handle(Guid id, CancellationToken token)
|
||||
{
|
||||
var doctor = await doctorRepository.GetByIdAsync(id, token);
|
||||
if (doctor == null)
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NotFound,
|
||||
Message = "Doctor was not found.",
|
||||
Data = null
|
||||
};
|
||||
|
||||
await doctorRepository.DeleteAsync(doctor, token);
|
||||
var criteria = new List<(string FieldName, string Value)>
|
||||
{
|
||||
("DoctorId", id.ToString())
|
||||
};
|
||||
var appointments = await appointmentsMongoDbService.FindAsync<Appointment>(criteria, token);
|
||||
if (appointments.Count != 0)
|
||||
await appointmentsMongoDbService.DeleteByIdAsync<Appointment>(appointments[0].Id, token);
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NoContent,
|
||||
Message = null,
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace Application.Endpoints.Doctors.ModifyDoctor;
|
||||
|
||||
public class ModifyDoctorCommand
|
||||
{
|
||||
public Guid Id { get; set; } = Guid.Empty;
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public string Email { get; set; } = string.Empty;
|
||||
public string Password { get; set; } = string.Empty;
|
||||
public string Description { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
using Application.Services.HashingAlgorithms;
|
||||
|
||||
namespace Application.Endpoints.Doctors.ModifyDoctor;
|
||||
|
||||
public class ModifyDoctorHandler(
|
||||
IHashingAlgorithms hashingAlgorithms,
|
||||
IDoctorRepository doctorRepository,
|
||||
IPatientRepository patientRepository,
|
||||
IAdminRepository adminRepository)
|
||||
{
|
||||
public async Task<BaseResponse> Handle(ModifyDoctorCommand request, CancellationToken token)
|
||||
{
|
||||
var validation = new ModifyDoctorValidator(doctorRepository, patientRepository, adminRepository);
|
||||
var validationResult = await validation.ValidateAsync(request, token);
|
||||
|
||||
if (!validationResult.IsValid)
|
||||
{
|
||||
var firstError = validationResult.Errors.FirstOrDefault();
|
||||
var errorCode = int.TryParse(firstError.ErrorCode, out var code) ? code : -1;
|
||||
var errorMessage = firstError.ErrorMessage;
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = errorCode,
|
||||
Message = errorMessage,
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
var newDoctor = await doctorRepository.GetByIdAsync(request.Id, token);
|
||||
|
||||
newDoctor.SetEmail(request.Email);
|
||||
newDoctor.SetPassword(hashingAlgorithms.Sha256Algorithm(request.Password));
|
||||
newDoctor.SetName(request.Name);
|
||||
newDoctor.SetDescription(request.Description);
|
||||
|
||||
await doctorRepository.UpdateAsync(newDoctor, token);
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NoContent,
|
||||
Message = null,
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
}
|
||||
+18
-14
@@ -1,25 +1,30 @@
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
using FluentValidation;
|
||||
|
||||
namespace Application.Endpoints.Doctors.Profile;
|
||||
namespace Application.Endpoints.Doctors.ModifyDoctor;
|
||||
|
||||
public class DoctorProfileValidation : AbstractValidator<DoctorProfileUpdateDto>
|
||||
public class ModifyDoctorValidator : AbstractValidator<ModifyDoctorCommand>
|
||||
{
|
||||
private readonly IDoctorRepository _doctorRepository;
|
||||
private readonly IPatientRepository _patientRepository;
|
||||
private readonly IAdminRepository _adminRepository;
|
||||
|
||||
public DoctorProfileValidation(IDoctorRepository doctorRepository)
|
||||
public ModifyDoctorValidator(IDoctorRepository doctorRepository,
|
||||
IPatientRepository patientRepository, IAdminRepository adminRepository)
|
||||
{
|
||||
_doctorRepository = doctorRepository;
|
||||
_patientRepository = patientRepository;
|
||||
_adminRepository = adminRepository;
|
||||
|
||||
RuleFor(x => x.Id)
|
||||
.NotEmpty().WithMessage("Id is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString())
|
||||
.MustAsync(IsDoctorRegistered).WithMessage("Doctor is not registered in system")
|
||||
.MustAsync(IsDoctorRegistered).WithMessage("Patient is not registered in system")
|
||||
.WithErrorCode(HttpStatusCodes.NotFound.ToString());
|
||||
|
||||
RuleFor(x => x.Email)
|
||||
.NotEmpty().WithMessage("Email is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString())
|
||||
.EmailAddress().WithMessage("Invalid email format.").WithErrorCode(HttpStatusCodes.BadRequest.ToString())
|
||||
.MustAsync(BeUniqueEmail).WithMessage("Email in use by another doctor.")
|
||||
.MustAsync(BeUniqueEmail).WithMessage("Email in use by another patient.")
|
||||
.WithErrorCode(HttpStatusCodes.Conflict.ToString());
|
||||
|
||||
RuleFor(x => x.Password)
|
||||
@@ -31,21 +36,20 @@ public class DoctorProfileValidation : AbstractValidator<DoctorProfileUpdateDto>
|
||||
.NotEmpty().WithMessage("Name is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString())
|
||||
.MinimumLength(3).WithMessage("Name must be at least 3 characters long.")
|
||||
.WithErrorCode(HttpStatusCodes.BadRequest.ToString());
|
||||
|
||||
RuleFor(x => x.Description)
|
||||
.MaximumLength(3000).WithMessage("Description must not exceed 3000 characters.")
|
||||
.WithErrorCode(HttpStatusCodes.BadRequest.ToString());
|
||||
}
|
||||
|
||||
private async Task<bool> IsDoctorRegistered(Guid id, CancellationToken cancellationToken)
|
||||
private async Task<bool> IsDoctorRegistered(Guid id, CancellationToken token)
|
||||
{
|
||||
var doctor = await _doctorRepository.GetByIdAsync(id);
|
||||
var doctor = await _doctorRepository.GetByIdAsync(id, token);
|
||||
return doctor != null;
|
||||
}
|
||||
|
||||
private async Task<bool> BeUniqueEmail(string email, CancellationToken cancellationToken)
|
||||
private async Task<bool> BeUniqueEmail(string email, CancellationToken token)
|
||||
{
|
||||
var doctor = await _doctorRepository.FindByEmailAsync(email);
|
||||
return doctor == null;
|
||||
var patient = await _patientRepository.FindByEmailAsync(email, token);
|
||||
var doctor = await _doctorRepository.FindByEmailAsync(email, token);
|
||||
var admin = await _adminRepository.FindByEmailAsync(email, token);
|
||||
|
||||
return patient == null && admin == null;
|
||||
}
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
using Application.Services.HashingAlgorithms;
|
||||
|
||||
namespace Application.Endpoints.Doctors.Profile;
|
||||
|
||||
public class DoctorProfileHandler
|
||||
{
|
||||
private readonly IDoctorRepository _database;
|
||||
private readonly IHashingAlgorithms _hashingAlgorithms;
|
||||
|
||||
public DoctorProfileHandler(IDoctorRepository database, IHashingAlgorithms hashingAlgorithms)
|
||||
{
|
||||
_database = database;
|
||||
_hashingAlgorithms = hashingAlgorithms;
|
||||
}
|
||||
|
||||
public async Task<BaseResponse> HandleGet(Guid id)
|
||||
{
|
||||
var doctor = await _database.GetByIdAsync(id).ConfigureAwait(false);
|
||||
if (doctor != null)
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.OK,
|
||||
Message = $"Retrieved doctor with id: {id}",
|
||||
Data = doctor
|
||||
};
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NotFound,
|
||||
Message = $"Doctor with id: {id} not found",
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<BaseResponse> HandleGetAll()
|
||||
{
|
||||
var doctors = await _database.GetAllAsync().ConfigureAwait(false);
|
||||
if (doctors.Any())
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.OK,
|
||||
Message = "Retrieved doctors",
|
||||
Data = doctors.ToList()
|
||||
};
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NoContent,
|
||||
Message = "Doctors not found",
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<BaseResponse> HandleUpdate(DoctorProfileUpdateDto doctorProfileUpdateDto)
|
||||
{
|
||||
var validation = new DoctorProfileValidation(_database);
|
||||
var validationResult = await validation.ValidateAsync(doctorProfileUpdateDto);
|
||||
|
||||
if (!validationResult.IsValid)
|
||||
{
|
||||
var firstError = validationResult.Errors.FirstOrDefault();
|
||||
var errorCode = int.TryParse(firstError.ErrorCode, out var code) ? code : -1;
|
||||
var errorMessage = firstError.ErrorMessage;
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = errorCode,
|
||||
Message = errorMessage,
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
var doctorToUpdate = await _database.GetByIdAsync(doctorProfileUpdateDto.Id);
|
||||
doctorToUpdate.SetEmail(doctorProfileUpdateDto.Email);
|
||||
doctorToUpdate.SetPassword(_hashingAlgorithms.SHA256Algorithm(doctorProfileUpdateDto.Password));
|
||||
doctorToUpdate.SetName(doctorProfileUpdateDto.Name);
|
||||
doctorToUpdate.SetDescription(doctorProfileUpdateDto.Description);
|
||||
|
||||
await _database.UpdateAsync(doctorToUpdate);
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NoContent,
|
||||
Message = null,
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<BaseResponse> HandleDelete(Guid id)
|
||||
{
|
||||
var doctorToDelete = await _database.GetByIdAsync(id);
|
||||
if (doctorToDelete == null)
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NotFound,
|
||||
Message = "Doctor was not found.",
|
||||
Data = null
|
||||
};
|
||||
|
||||
await _database.DeleteAsync(doctorToDelete);
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NoContent,
|
||||
Message = null,
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
namespace Application.Endpoints.Doctors.Profile;
|
||||
|
||||
public class DoctorProfileUpdateDto
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Email { get; set; }
|
||||
public string Password { get; set; }
|
||||
public string Description { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
|
||||
namespace Application.Endpoints.Doctors.QuerriesDoctors;
|
||||
|
||||
public class QuerriesDoctorsHandler(IDoctorRepository database)
|
||||
{
|
||||
public async Task<BaseResponse> HandleGet(Guid id, CancellationToken token)
|
||||
{
|
||||
var doctor = await database.GetByIdAsync(id, token);
|
||||
if (doctor != null)
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.OK,
|
||||
Message = $"Retrieved doctor with id: {id}",
|
||||
Data = doctor
|
||||
};
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NotFound,
|
||||
Message = $"Doctor with id: {id} not found",
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<BaseResponse> HandleGetAll(CancellationToken token)
|
||||
{
|
||||
var doctors = await database.GetAllAsync(token);
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.OK,
|
||||
Message = "Retrieved doctors",
|
||||
Data = doctors.ToList()
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace Application.Endpoints.Doctors.Registration;
|
||||
|
||||
public class DoctorRegistrationDto
|
||||
{
|
||||
public string? Name { get; set; }
|
||||
public string? Email { get; set; }
|
||||
public string? Password { get; set; }
|
||||
public string? Description { get; set; }
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
using Application.Services.HashingAlgorithms;
|
||||
using Core.Entities;
|
||||
|
||||
namespace Application.Endpoints.Doctors.Registration;
|
||||
|
||||
public class DoctorRegistrationHandler
|
||||
{
|
||||
private readonly IDoctorRepository _doctorRepository;
|
||||
private readonly IHashingAlgorithms _hashingAlgorithms;
|
||||
|
||||
public DoctorRegistrationHandler(IDoctorRepository doctorRepository, IHashingAlgorithms hashingAlgorithms)
|
||||
{
|
||||
_doctorRepository = doctorRepository;
|
||||
_hashingAlgorithms = hashingAlgorithms;
|
||||
}
|
||||
|
||||
public async Task<BaseResponse> Handle(DoctorRegistrationDto registrationDTO)
|
||||
{
|
||||
var validation = new DoctorRegistrationValidation(_doctorRepository);
|
||||
var validationResult = await validation.ValidateAsync(registrationDTO);
|
||||
|
||||
if (!validationResult.IsValid)
|
||||
{
|
||||
var firstError = validationResult.Errors.FirstOrDefault();
|
||||
var errorCode = int.TryParse(firstError.ErrorCode, out var code) ? code : -1;
|
||||
var errorMessage = firstError.ErrorMessage;
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = errorCode,
|
||||
Message = errorMessage,
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
var doctor = new Doctor();
|
||||
doctor.SetEmail(registrationDTO.Email);
|
||||
doctor.SetPassword(_hashingAlgorithms.SHA256Algorithm(registrationDTO.Password));
|
||||
doctor.SetName(registrationDTO.Name);
|
||||
doctor.SetDescription(registrationDTO.Description);
|
||||
|
||||
await _doctorRepository.AddAsync(doctor);
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.Created,
|
||||
Message = "Doctor registered successfully",
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
using FluentValidation;
|
||||
|
||||
namespace Application.Endpoints.Doctors.Registration;
|
||||
|
||||
public class DoctorRegistrationValidation : AbstractValidator<DoctorRegistrationDto>
|
||||
{
|
||||
private readonly IDoctorRepository _doctorRepository;
|
||||
|
||||
public DoctorRegistrationValidation(IDoctorRepository doctorRepository)
|
||||
{
|
||||
_doctorRepository = doctorRepository;
|
||||
|
||||
RuleFor(x => x.Email)
|
||||
.NotEmpty().WithMessage("Email is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString())
|
||||
.EmailAddress().WithMessage("Invalid email format.").WithErrorCode(HttpStatusCodes.BadRequest.ToString())
|
||||
.MustAsync(BeUniqueEmail).WithMessage("Email already exists.")
|
||||
.WithErrorCode(HttpStatusCodes.Conflict.ToString());
|
||||
|
||||
RuleFor(x => x.Password)
|
||||
.NotEmpty().WithMessage("Password is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString())
|
||||
.MinimumLength(8).WithMessage("Password must be at least 8 characters long.")
|
||||
.WithErrorCode(HttpStatusCodes.BadRequest.ToString());
|
||||
|
||||
RuleFor(x => x.Name)
|
||||
.NotEmpty().WithMessage("Name is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString())
|
||||
.MinimumLength(3).WithMessage("Name must be at least 3 characters long.")
|
||||
.WithErrorCode(HttpStatusCodes.BadRequest.ToString());
|
||||
|
||||
RuleFor(x => x.Description)
|
||||
.MaximumLength(3000).WithMessage("Description must not exceed 3000 characters.")
|
||||
.WithErrorCode(HttpStatusCodes.BadRequest.ToString());
|
||||
}
|
||||
|
||||
private async Task<bool> BeUniqueEmail(string email, CancellationToken cancellationToken)
|
||||
{
|
||||
var doctor = await _doctorRepository.FindByEmailAsync(email);
|
||||
return doctor == null;
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
namespace Application.Endpoints.MedicalHistories.CreateMedicalHistory;
|
||||
|
||||
public class CreateMedicalHistoryCommand
|
||||
{
|
||||
public Guid UserId { get; set; }
|
||||
public byte[] Content { get; set; } = [];
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
using Application.Endpoints.MedicalHistories.ManageAuthorization;
|
||||
using Application.Services.Database.MongoDB;
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
using Domain.Entities;
|
||||
|
||||
namespace Application.Endpoints.MedicalHistories.CreateMedicalHistory;
|
||||
|
||||
public class CreateMedicalHistoryHandler(
|
||||
IMedicalHistoryRepository medicalHistoryRepository,
|
||||
IPatientRepository patientRepository,
|
||||
IMedicalHistoryMongoDbService medicalHistoryMongoDbService)
|
||||
{
|
||||
public async Task<BaseResponse> Handle(CreateMedicalHistoryCommand request, CancellationToken token)
|
||||
{
|
||||
var validation = new CreateMedicalHistoryValidator(patientRepository);
|
||||
var validationResult = await validation.ValidateAsync(request, token);
|
||||
|
||||
if (!validationResult.IsValid)
|
||||
{
|
||||
var firstError = validationResult.Errors.FirstOrDefault();
|
||||
var errorCode = int.TryParse(firstError.ErrorCode, out var code) ? code : -1;
|
||||
var errorMessage = firstError.ErrorMessage;
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = errorCode,
|
||||
Message = errorMessage,
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
var medicalHistory = new MedicalHistory();
|
||||
medicalHistory.SetUserId(request.UserId);
|
||||
medicalHistory.SetContent(request.Content);
|
||||
|
||||
var medicalHistoryId = medicalHistory.Id;
|
||||
var newMedicalHistory = new MedicalHistoryAuthorisationModel
|
||||
{
|
||||
Id = medicalHistoryId.ToString(),
|
||||
Authorisation = new List<string>()
|
||||
};
|
||||
|
||||
await medicalHistoryMongoDbService.AddAsync(newMedicalHistory, token);
|
||||
await medicalHistoryRepository.AddAsync(medicalHistory, token);
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.Created,
|
||||
Message = "Medical history record registered successfully",
|
||||
Data = medicalHistory
|
||||
};
|
||||
}
|
||||
}
|
||||
+5
-5
@@ -1,13 +1,13 @@
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
using FluentValidation;
|
||||
|
||||
namespace Application.Endpoints.MedicalHistories;
|
||||
namespace Application.Endpoints.MedicalHistories.CreateMedicalHistory;
|
||||
|
||||
public class MedicalHistoryCreateValidation : AbstractValidator<MedicalHistoryCreateDto>
|
||||
public class CreateMedicalHistoryValidator : AbstractValidator<CreateMedicalHistoryCommand>
|
||||
{
|
||||
private readonly IPatientRepository _patientRepository;
|
||||
|
||||
public MedicalHistoryCreateValidation(IPatientRepository patientRepository)
|
||||
public CreateMedicalHistoryValidator(IPatientRepository patientRepository)
|
||||
{
|
||||
_patientRepository = patientRepository;
|
||||
|
||||
@@ -20,9 +20,9 @@ public class MedicalHistoryCreateValidation : AbstractValidator<MedicalHistoryCr
|
||||
.NotEmpty().WithMessage("Description is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString());
|
||||
}
|
||||
|
||||
private async Task<bool> BeExistingUser(Guid userId, CancellationToken cancellationToken)
|
||||
private async Task<bool> BeExistingUser(Guid userId, CancellationToken token)
|
||||
{
|
||||
var patient = await _patientRepository.GetByIdAsync(userId);
|
||||
var patient = await _patientRepository.GetByIdAsync(userId, token);
|
||||
return patient != null;
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
using Application.Endpoints.MedicalHistories.ManageAuthorization;
|
||||
using Application.Services.Database.MongoDB;
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
|
||||
namespace Application.Endpoints.MedicalHistories.DeleteMedicalHistory;
|
||||
|
||||
public class DeleteMedicalHistoryHandler(
|
||||
IMedicalHistoryRepository medicalHistoryRepository,
|
||||
IMedicalHistoryMongoDbService medicalHistoryMongoDbService)
|
||||
{
|
||||
public async Task<BaseResponse> Handle(Guid id, CancellationToken token)
|
||||
{
|
||||
var medicalRecord = await medicalHistoryRepository.GetByIdAsync(id, token);
|
||||
if (medicalRecord == null)
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NotFound,
|
||||
Message = "Medical record is not in system.",
|
||||
Data = null
|
||||
};
|
||||
|
||||
await medicalHistoryRepository.DeleteAsync(medicalRecord, token);
|
||||
await medicalHistoryMongoDbService.DeleteAsync<MedicalHistoryAuthorisationModel>(
|
||||
"_id", id.ToString(), token);
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NoContent,
|
||||
Message = null,
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
}
|
||||
-7
@@ -1,7 +0,0 @@
|
||||
namespace Application.Endpoints.MedicalHistories.FileManagement;
|
||||
|
||||
public class MedicalHistoryCreateDto
|
||||
{
|
||||
public Guid UserId { get; set; }
|
||||
public byte[] Content { get; set; } = [];
|
||||
}
|
||||
-28
@@ -1,28 +0,0 @@
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
using FluentValidation;
|
||||
|
||||
namespace Application.Endpoints.MedicalHistories.FileManagement;
|
||||
|
||||
public class MedicalHistoryCreateValidation : AbstractValidator<MedicalHistoryCreateDto>
|
||||
{
|
||||
private readonly IPatientRepository _patientRepository;
|
||||
|
||||
public MedicalHistoryCreateValidation(IPatientRepository patientRepository)
|
||||
{
|
||||
_patientRepository = patientRepository;
|
||||
|
||||
RuleFor(x => x.UserId)
|
||||
.NotEmpty().WithMessage("Patient is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString())
|
||||
.MustAsync(BeExistingUser).WithMessage("Specified patient doesn't exist.")
|
||||
.WithErrorCode(HttpStatusCodes.NotFound.ToString());
|
||||
|
||||
RuleFor(x => x.Content)
|
||||
.NotEmpty().WithMessage("Description is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString());
|
||||
}
|
||||
|
||||
private async Task<bool> BeExistingUser(Guid userId, CancellationToken cancellationToken)
|
||||
{
|
||||
var patient = await _patientRepository.GetByIdAsync(userId);
|
||||
return patient != null;
|
||||
}
|
||||
}
|
||||
-156
@@ -1,156 +0,0 @@
|
||||
using Application.Services.Database.MongoDB;
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
using Core.Entities;
|
||||
|
||||
namespace Application.Endpoints.MedicalHistories.FileManagement;
|
||||
|
||||
public class MedicalHistoryFileManagementHandler
|
||||
{
|
||||
private readonly IMedicalHistoryMongoDbService _medicalHistoryMongoDbService;
|
||||
private readonly IMedicalHistoryRepository _medicalHistoryRepository;
|
||||
private readonly IPatientRepository _patientRepository;
|
||||
|
||||
public MedicalHistoryFileManagementHandler(IMedicalHistoryRepository medicalHistoryRepository,
|
||||
IPatientRepository patientRepository, IMedicalHistoryMongoDbService medicalHistoryMongoDbService)
|
||||
{
|
||||
_medicalHistoryRepository = medicalHistoryRepository;
|
||||
_patientRepository = patientRepository;
|
||||
_medicalHistoryMongoDbService = medicalHistoryMongoDbService;
|
||||
}
|
||||
|
||||
public async Task<BaseResponse> HandleGetAll()
|
||||
{
|
||||
var documents = await _medicalHistoryRepository.GetAllAsync().ConfigureAwait(false);
|
||||
if (documents.Any())
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.OK,
|
||||
Message = "Retrieved medical histories",
|
||||
Data = documents.ToList()
|
||||
};
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NotFound,
|
||||
Message = "Medical histories not found",
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<BaseResponse> HandleGet(Guid id)
|
||||
{
|
||||
var medicalHistory = await _medicalHistoryRepository.GetByIdAsync(id).ConfigureAwait(false);
|
||||
if (medicalHistory != null)
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.OK,
|
||||
Message = "Medical history successfully retrieved",
|
||||
Data = medicalHistory
|
||||
};
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NotFound,
|
||||
Message = "Medical history not found in system.",
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<BaseResponse> HandleCreate(MedicalHistoryCreateDto medicalHistoryCreateDto)
|
||||
{
|
||||
var validation = new MedicalHistoryCreateValidation(_patientRepository);
|
||||
var validationResult = await validation.ValidateAsync(medicalHistoryCreateDto);
|
||||
|
||||
if (!validationResult.IsValid)
|
||||
{
|
||||
var firstError = validationResult.Errors.FirstOrDefault();
|
||||
var errorCode = int.TryParse(firstError.ErrorCode, out var code) ? code : -1;
|
||||
var errorMessage = firstError.ErrorMessage;
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = errorCode,
|
||||
Message = errorMessage,
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
var medicalHistory = new MedicalHistory
|
||||
{
|
||||
UserId = medicalHistoryCreateDto.UserId,
|
||||
Content = medicalHistoryCreateDto.Content
|
||||
};
|
||||
|
||||
var medicalHistoryId = medicalHistory.Id;
|
||||
var newMedicalHistory = new MedicalHistoryAuthorisationModel
|
||||
{
|
||||
Id = medicalHistoryId.ToString(),
|
||||
Authorisation = new List<string>()
|
||||
};
|
||||
|
||||
await _medicalHistoryMongoDbService.AddAsync(newMedicalHistory);
|
||||
await _medicalHistoryRepository.AddAsync(medicalHistory);
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.Created,
|
||||
Message = "Medical history record registered successfully",
|
||||
Data = medicalHistory
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<BaseResponse> HandleUpdate(MedicalHistoryUpdateDto updateDto)
|
||||
{
|
||||
var validation = new MedicalHistoryUpdateValidation(_medicalHistoryRepository, _patientRepository);
|
||||
var validationResult = await validation.ValidateAsync(updateDto);
|
||||
|
||||
if (!validationResult.IsValid)
|
||||
{
|
||||
var firstError = validationResult.Errors.FirstOrDefault();
|
||||
var errorCode = int.TryParse(firstError.ErrorCode, out var code) ? code : -1;
|
||||
var errorMessage = firstError.ErrorMessage;
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = errorCode,
|
||||
Message = errorMessage,
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
var medicalHistoryToUpdate = await _medicalHistoryRepository.GetByIdAsync(updateDto.Id);
|
||||
medicalHistoryToUpdate.Content = updateDto.Content;
|
||||
|
||||
await _medicalHistoryRepository.UpdateAsync(medicalHistoryToUpdate);
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NoContent,
|
||||
Message = "Medical record updated successfully",
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<BaseResponse> HandleDelete(Guid id)
|
||||
{
|
||||
var medicalRecord = await _medicalHistoryRepository.GetByIdAsync(id);
|
||||
if (medicalRecord == null)
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NotFound,
|
||||
Message = "Medical record is not in system.",
|
||||
Data = null
|
||||
};
|
||||
|
||||
await _medicalHistoryMongoDbService.DeleteAsync<MedicalHistoryAuthorisationModel>("_id", id.ToString());
|
||||
|
||||
await _medicalHistoryRepository.DeleteAsync(medicalRecord);
|
||||
|
||||
//TODO delete from MongoDB
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NoContent,
|
||||
Message = null,
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
}
|
||||
-7
@@ -1,7 +0,0 @@
|
||||
namespace Application.Endpoints.MedicalHistories.FileManagement;
|
||||
|
||||
public class MedicalHistoryUpdateDto
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public byte[] Content { get; set; } = [];
|
||||
}
|
||||
-30
@@ -1,30 +0,0 @@
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
using FluentValidation;
|
||||
|
||||
namespace Application.Endpoints.MedicalHistories.FileManagement;
|
||||
|
||||
public class MedicalHistoryUpdateValidation : AbstractValidator<MedicalHistoryUpdateDto>
|
||||
{
|
||||
private readonly IMedicalHistoryRepository _medicalHistoryRepository;
|
||||
private readonly IPatientRepository _patientRepository;
|
||||
|
||||
public MedicalHistoryUpdateValidation(IMedicalHistoryRepository medicalHistoryRepository,
|
||||
IPatientRepository patientRepository)
|
||||
{
|
||||
_medicalHistoryRepository = medicalHistoryRepository;
|
||||
_patientRepository = patientRepository;
|
||||
|
||||
RuleFor(x => x.Id)
|
||||
.NotEmpty().WithMessage("Id is required")
|
||||
.MustAsync(BeExistingMedicalHistoryRecord).WithMessage("Medical history record does not exist");
|
||||
|
||||
RuleFor(x => x.Content)
|
||||
.NotEmpty().WithMessage("Description is required.");
|
||||
}
|
||||
|
||||
private async Task<bool> BeExistingMedicalHistoryRecord(Guid guid, CancellationToken token)
|
||||
{
|
||||
var record = await _medicalHistoryRepository.GetByIdAsync(guid);
|
||||
return record != null;
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
namespace Application.Endpoints.MedicalHistories.ManageAuthorization;
|
||||
|
||||
public class MedicalHistoryAuthorizationInfo
|
||||
{
|
||||
public Guid MedicalRecordId { get; set; } = Guid.Empty;
|
||||
public Guid DoctorId { get; set; } = Guid.Empty;
|
||||
}
|
||||
-7
@@ -1,7 +0,0 @@
|
||||
namespace Application.Endpoints.MedicalHistories.ManageAuthorization;
|
||||
|
||||
public class MedicalHistoryManageAuthorizationDoctorDto
|
||||
{
|
||||
public Guid MedicalRecordId { get; set; }
|
||||
public Guid DoctorId { get; set; }
|
||||
}
|
||||
+77
-31
@@ -3,24 +3,16 @@ using Application.Services.Database.PostgreSQL;
|
||||
|
||||
namespace Application.Endpoints.MedicalHistories.ManageAuthorization;
|
||||
|
||||
public class MedicalHistoryManageAuthorizationHandler
|
||||
public class MedicalHistoryManageAuthorizationHandler(
|
||||
IMedicalHistoryRepository medicalHistoryRepository,
|
||||
IMedicalHistoryMongoDbService medicalHistoryMongoDbService,
|
||||
IDoctorRepository doctorRepository)
|
||||
{
|
||||
private readonly IDoctorRepository _doctorRepository;
|
||||
private readonly IMedicalHistoryMongoDbService _medicalHistoryMongoDbService;
|
||||
private readonly IMedicalHistoryRepository _medicalHistoryRepository;
|
||||
|
||||
public MedicalHistoryManageAuthorizationHandler(IMedicalHistoryRepository medicalHistoryRepository,
|
||||
IMedicalHistoryMongoDbService medicalHistoryMongoDbService, IDoctorRepository doctorRepository)
|
||||
public async Task<BaseResponse> HandleGrantDoctorAccess(
|
||||
MedicalHistoryAuthorizationInfo request, CancellationToken token)
|
||||
{
|
||||
_medicalHistoryRepository = medicalHistoryRepository;
|
||||
_medicalHistoryMongoDbService = medicalHistoryMongoDbService;
|
||||
_doctorRepository = doctorRepository;
|
||||
}
|
||||
|
||||
public async Task<BaseResponse> HandleGrantDoctorAccess(MedicalHistoryManageAuthorizationDoctorDto infoDto)
|
||||
{
|
||||
var validation = new MedicalHistoryManageAuthorizationValidation(_medicalHistoryRepository, _doctorRepository);
|
||||
var validationResult = await validation.ValidateAsync(infoDto);
|
||||
var validation = new MedicalHistoryManageAuthorizationValidator(medicalHistoryRepository, doctorRepository);
|
||||
var validationResult = await validation.ValidateAsync(request, token);
|
||||
|
||||
if (!validationResult.IsValid)
|
||||
{
|
||||
@@ -37,9 +29,10 @@ public class MedicalHistoryManageAuthorizationHandler
|
||||
}
|
||||
|
||||
var criteria = new List<(string, string)>();
|
||||
criteria.Add(("_id", infoDto.MedicalRecordId.ToString()));
|
||||
criteria.Add(("_id", request.MedicalRecordId.ToString()));
|
||||
|
||||
var documents = await _medicalHistoryMongoDbService.FindAsync<MedicalHistoryAuthorisationModel>(criteria);
|
||||
var documents =
|
||||
await medicalHistoryMongoDbService.FindAsync<MedicalHistoryAuthorisationModel>(criteria, token);
|
||||
if (!documents.Any())
|
||||
return new BaseResponse
|
||||
{
|
||||
@@ -49,7 +42,7 @@ public class MedicalHistoryManageAuthorizationHandler
|
||||
};
|
||||
|
||||
var authorisations = documents[0].Authorisation;
|
||||
if (authorisations.Contains(infoDto.ToString()))
|
||||
if (authorisations.Contains(request.ToString()))
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.Conflict,
|
||||
@@ -57,14 +50,15 @@ public class MedicalHistoryManageAuthorizationHandler
|
||||
Data = null
|
||||
};
|
||||
|
||||
authorisations.Add(infoDto.DoctorId.ToString());
|
||||
authorisations.Add(request.DoctorId.ToString());
|
||||
var authorizationModel = new MedicalHistoryAuthorisationModel
|
||||
{
|
||||
Id = infoDto.MedicalRecordId.ToString(),
|
||||
Id = request.MedicalRecordId.ToString(),
|
||||
Authorisation = authorisations
|
||||
};
|
||||
|
||||
await _medicalHistoryMongoDbService.ModifyAsync("_id", infoDto.MedicalRecordId.ToString(), authorizationModel);
|
||||
await medicalHistoryMongoDbService.ModifyAsync(
|
||||
"_id", request.MedicalRecordId.ToString(), authorizationModel, token);
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
@@ -74,10 +68,11 @@ public class MedicalHistoryManageAuthorizationHandler
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<BaseResponse> HandleRevokeDoctorAccess(MedicalHistoryManageAuthorizationDoctorDto infoDto)
|
||||
public async Task<BaseResponse> HandleRevokeDoctorAccess(
|
||||
MedicalHistoryAuthorizationInfo request, CancellationToken token)
|
||||
{
|
||||
var validation = new MedicalHistoryManageAuthorizationValidation(_medicalHistoryRepository, _doctorRepository);
|
||||
var validationResult = await validation.ValidateAsync(infoDto);
|
||||
var validation = new MedicalHistoryManageAuthorizationValidator(medicalHistoryRepository, doctorRepository);
|
||||
var validationResult = await validation.ValidateAsync(request, token);
|
||||
|
||||
if (!validationResult.IsValid)
|
||||
{
|
||||
@@ -94,9 +89,10 @@ public class MedicalHistoryManageAuthorizationHandler
|
||||
}
|
||||
|
||||
var criteria = new List<(string, string)>();
|
||||
criteria.Add(("_id", infoDto.MedicalRecordId.ToString()));
|
||||
criteria.Add(("_id", request.MedicalRecordId.ToString()));
|
||||
|
||||
var documents = await _medicalHistoryMongoDbService.FindAsync<MedicalHistoryAuthorisationModel>(criteria);
|
||||
var documents = await medicalHistoryMongoDbService
|
||||
.FindAsync<MedicalHistoryAuthorisationModel>(criteria, token);
|
||||
if (!documents.Any())
|
||||
return new BaseResponse
|
||||
{
|
||||
@@ -106,7 +102,7 @@ public class MedicalHistoryManageAuthorizationHandler
|
||||
};
|
||||
|
||||
var authorisations = documents[0].Authorisation;
|
||||
if (!authorisations.Contains(infoDto.DoctorId.ToString()))
|
||||
if (!authorisations.Contains(request.DoctorId.ToString()))
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.Conflict,
|
||||
@@ -114,14 +110,15 @@ public class MedicalHistoryManageAuthorizationHandler
|
||||
Data = null
|
||||
};
|
||||
|
||||
authorisations.Remove(infoDto.DoctorId.ToString());
|
||||
authorisations.Remove(request.DoctorId.ToString());
|
||||
var authorizationModel = new MedicalHistoryAuthorisationModel
|
||||
{
|
||||
Id = infoDto.MedicalRecordId.ToString(),
|
||||
Id = request.MedicalRecordId.ToString(),
|
||||
Authorisation = authorisations
|
||||
};
|
||||
|
||||
await _medicalHistoryMongoDbService.ModifyAsync("_id", infoDto.MedicalRecordId.ToString(), authorizationModel);
|
||||
await medicalHistoryMongoDbService.ModifyAsync(
|
||||
"_id", request.MedicalRecordId.ToString(), authorizationModel, token);
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
@@ -130,4 +127,53 @@ public class MedicalHistoryManageAuthorizationHandler
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<BaseResponse> HandleCheckAccessToMedicalHistory(
|
||||
MedicalHistoryAuthorizationInfo request, CancellationToken token)
|
||||
{
|
||||
var validation = new MedicalHistoryManageAuthorizationValidator(medicalHistoryRepository, doctorRepository);
|
||||
var validationResult = await validation.ValidateAsync(request, token);
|
||||
|
||||
if (!validationResult.IsValid)
|
||||
{
|
||||
var firstError = validationResult.Errors.FirstOrDefault();
|
||||
var errorCode = int.TryParse(firstError.ErrorCode, out var code) ? code : -1;
|
||||
var errorMessage = firstError.ErrorMessage;
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = errorCode,
|
||||
Message = errorMessage,
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
var criteria = new List<(string, string)>();
|
||||
criteria.Add(("_id", request.MedicalRecordId.ToString()));
|
||||
var documents = await medicalHistoryMongoDbService
|
||||
.FindAsync<MedicalHistoryAuthorisationModel>(criteria, token);
|
||||
if (!documents.Any())
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NotFound,
|
||||
Message = "Access to medical history not found.",
|
||||
Data = null
|
||||
};
|
||||
|
||||
var authorisations = documents[0].Authorisation;
|
||||
if (!authorisations.Contains(request.DoctorId.ToString()))
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NotFound,
|
||||
Message = "Access to medical history is revoked.",
|
||||
Data = null
|
||||
};
|
||||
|
||||
return new BaseResponse()
|
||||
{
|
||||
StatusCode = HttpStatusCodes.OK,
|
||||
Message = "Access to medical history is granted",
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
}
|
||||
+5
-5
@@ -3,12 +3,12 @@ using FluentValidation;
|
||||
|
||||
namespace Application.Endpoints.MedicalHistories.ManageAuthorization;
|
||||
|
||||
public class MedicalHistoryManageAuthorizationValidation : AbstractValidator<MedicalHistoryManageAuthorizationDoctorDto>
|
||||
public class MedicalHistoryManageAuthorizationValidator : AbstractValidator<MedicalHistoryAuthorizationInfo>
|
||||
{
|
||||
private readonly IDoctorRepository _doctorRepository;
|
||||
private readonly IMedicalHistoryRepository _medicalHistoryRepository;
|
||||
|
||||
public MedicalHistoryManageAuthorizationValidation(IMedicalHistoryRepository medicalHistoryRepository,
|
||||
public MedicalHistoryManageAuthorizationValidator(IMedicalHistoryRepository medicalHistoryRepository,
|
||||
IDoctorRepository doctorRepository)
|
||||
{
|
||||
RuleFor(x => x.MedicalRecordId)
|
||||
@@ -27,13 +27,13 @@ public class MedicalHistoryManageAuthorizationValidation : AbstractValidator<Med
|
||||
|
||||
private async Task<bool> BeExistingMedicalHistoryRecord(Guid guid, CancellationToken token)
|
||||
{
|
||||
var record = await _medicalHistoryRepository.GetByIdAsync(guid);
|
||||
var record = await _medicalHistoryRepository.GetByIdAsync(guid, token);
|
||||
return record != null;
|
||||
}
|
||||
|
||||
private async Task<bool> IsDoctorRegistered(Guid id, CancellationToken cancellationToken)
|
||||
private async Task<bool> IsDoctorRegistered(Guid id, CancellationToken token)
|
||||
{
|
||||
var doctor = await _doctorRepository.GetByIdAsync(id);
|
||||
var doctor = await _doctorRepository.GetByIdAsync(id, token);
|
||||
return doctor != null;
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,6 @@
|
||||
|
||||
public class MedicalHistoryAuthorisationModel
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public List<string> Authorisation { get; set; } = new();
|
||||
public string Id { get; set; } = string.Empty;
|
||||
public List<string> Authorisation { get; set; } = [];
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace Application.Endpoints.MedicalHistories;
|
||||
|
||||
public class MedicalHistoryCreateDto
|
||||
{
|
||||
public Guid UserId { get; set; }
|
||||
public byte[] Content { get; set; } = [];
|
||||
}
|
||||
@@ -1,156 +0,0 @@
|
||||
using Application.Services.Database.MongoDB;
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
using Core.Entities;
|
||||
|
||||
namespace Application.Endpoints.MedicalHistories;
|
||||
|
||||
public class MedicalHistoryHandler
|
||||
{
|
||||
private readonly IMedicalHistoryMongoDbService _medicalHistoryMongoDbService;
|
||||
private readonly IMedicalHistoryRepository _medicalHistoryRepository;
|
||||
private readonly IPatientRepository _patientRepository;
|
||||
|
||||
public MedicalHistoryHandler(IMedicalHistoryRepository medicalHistoryRepository,
|
||||
IPatientRepository patientRepository, IMedicalHistoryMongoDbService medicalHistoryMongoDbService)
|
||||
{
|
||||
_medicalHistoryRepository = medicalHistoryRepository;
|
||||
_patientRepository = patientRepository;
|
||||
_medicalHistoryMongoDbService = medicalHistoryMongoDbService;
|
||||
}
|
||||
|
||||
public async Task<BaseResponse> HandleGetAll()
|
||||
{
|
||||
var documents = await _medicalHistoryRepository.GetAllAsync().ConfigureAwait(false);
|
||||
if (documents.Any())
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.OK,
|
||||
Message = "Retrieved medical histories",
|
||||
Data = documents.ToList()
|
||||
};
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NoContent,
|
||||
Message = "Medical histories not found",
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<BaseResponse> HandleGet(Guid id)
|
||||
{
|
||||
var medicalHistory = await _medicalHistoryRepository.GetByIdAsync(id).ConfigureAwait(false);
|
||||
if (medicalHistory != null)
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.OK,
|
||||
Message = "Medical history successfully retrieved",
|
||||
Data = medicalHistory
|
||||
};
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NotFound,
|
||||
Message = "Medical history not found in system.",
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<BaseResponse> HandleCreate(MedicalHistoryCreateDto medicalHistoryCreateDto)
|
||||
{
|
||||
var validation = new MedicalHistoryCreateValidation(_patientRepository);
|
||||
var validationResult = await validation.ValidateAsync(medicalHistoryCreateDto);
|
||||
|
||||
if (!validationResult.IsValid)
|
||||
{
|
||||
var firstError = validationResult.Errors.FirstOrDefault();
|
||||
var errorCode = int.TryParse(firstError.ErrorCode, out var code) ? code : -1;
|
||||
var errorMessage = firstError.ErrorMessage;
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = errorCode,
|
||||
Message = errorMessage,
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
var medicalHistory = new MedicalHistory
|
||||
{
|
||||
UserId = medicalHistoryCreateDto.UserId,
|
||||
Content = medicalHistoryCreateDto.Content
|
||||
};
|
||||
|
||||
var medicalHistoryId = medicalHistory.Id;
|
||||
var newMedicalHistory = new MedicalHistoryAuthorisationModel
|
||||
{
|
||||
Id = medicalHistoryId.ToString(),
|
||||
Authorisation = new List<string>()
|
||||
};
|
||||
|
||||
await _medicalHistoryMongoDbService.AddAsync(newMedicalHistory);
|
||||
await _medicalHistoryRepository.AddAsync(medicalHistory);
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.Created,
|
||||
Message = "Medical history record registered successfully",
|
||||
Data = medicalHistory
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<BaseResponse> HandleUpdate(MedicalHistoryUpdateDto updateDto)
|
||||
{
|
||||
var validation = new MedicalHistoryUpdateValidation(_medicalHistoryRepository, _patientRepository);
|
||||
var validationResult = await validation.ValidateAsync(updateDto);
|
||||
|
||||
if (!validationResult.IsValid)
|
||||
{
|
||||
var firstError = validationResult.Errors.FirstOrDefault();
|
||||
var errorCode = int.TryParse(firstError.ErrorCode, out var code) ? code : -1;
|
||||
var errorMessage = firstError.ErrorMessage;
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = errorCode,
|
||||
Message = errorMessage,
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
var medicalHistoryToUpdate = await _medicalHistoryRepository.GetByIdAsync(updateDto.Id);
|
||||
medicalHistoryToUpdate.Content = updateDto.Content;
|
||||
|
||||
await _medicalHistoryRepository.UpdateAsync(medicalHistoryToUpdate);
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NoContent,
|
||||
Message = "Medical record updated successfully",
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<BaseResponse> HandleDelete(Guid id)
|
||||
{
|
||||
var medicalRecord = await _medicalHistoryRepository.GetByIdAsync(id);
|
||||
if (medicalRecord == null)
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NotFound,
|
||||
Message = "Medical record is not in system.",
|
||||
Data = null
|
||||
};
|
||||
|
||||
await _medicalHistoryMongoDbService.DeleteAsync<MedicalHistoryAuthorisationModel>("_id", id.ToString());
|
||||
|
||||
await _medicalHistoryRepository.DeleteAsync(medicalRecord);
|
||||
|
||||
//TODO delete from MongoDB
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NoContent,
|
||||
Message = null,
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace Application.Endpoints.MedicalHistories;
|
||||
|
||||
public class MedicalHistoryUpdateDto
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public byte[] Content { get; set; } = [];
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
namespace Application.Endpoints.MedicalHistories.ModifyMedicalHistory;
|
||||
|
||||
public class ModifyMedicalHistoryCommand
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public byte[] Content { get; set; } = [];
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
using Application.Services.Database.MongoDB;
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
|
||||
namespace Application.Endpoints.MedicalHistories.ModifyMedicalHistory;
|
||||
|
||||
public class ModifyMedicalHistoryHandler(IMedicalHistoryRepository medicalHistoryRepository)
|
||||
{
|
||||
public async Task<BaseResponse> Handle(ModifyMedicalHistoryCommand request, CancellationToken token)
|
||||
{
|
||||
var validation = new ModifyMedicalHistoryValidator(medicalHistoryRepository);
|
||||
var validationResult = await validation.ValidateAsync(request, token);
|
||||
|
||||
if (!validationResult.IsValid)
|
||||
{
|
||||
var firstError = validationResult.Errors.FirstOrDefault();
|
||||
var errorCode = int.TryParse(firstError.ErrorCode, out var code) ? code : -1;
|
||||
var errorMessage = firstError.ErrorMessage;
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = errorCode,
|
||||
Message = errorMessage,
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
var newMedicalHistory = await medicalHistoryRepository.GetByIdAsync(request.Id, token);
|
||||
newMedicalHistory.SetContent(request.Content);
|
||||
|
||||
await medicalHistoryRepository.UpdateAsync(newMedicalHistory, token);
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NoContent,
|
||||
Message = "Medical record updated successfully",
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
}
|
||||
+5
-8
@@ -1,18 +1,15 @@
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
using FluentValidation;
|
||||
|
||||
namespace Application.Endpoints.MedicalHistories;
|
||||
namespace Application.Endpoints.MedicalHistories.ModifyMedicalHistory;
|
||||
|
||||
public class MedicalHistoryUpdateValidation : AbstractValidator<MedicalHistoryUpdateDto>
|
||||
public class ModifyMedicalHistoryValidator : AbstractValidator<ModifyMedicalHistoryCommand>
|
||||
{
|
||||
private readonly IMedicalHistoryRepository _medicalHistoryRepository;
|
||||
private readonly IPatientRepository _patientRepository;
|
||||
|
||||
public MedicalHistoryUpdateValidation(IMedicalHistoryRepository medicalHistoryRepository,
|
||||
IPatientRepository patientRepository)
|
||||
public ModifyMedicalHistoryValidator(IMedicalHistoryRepository medicalHistoryRepository)
|
||||
{
|
||||
_medicalHistoryRepository = medicalHistoryRepository;
|
||||
_patientRepository = patientRepository;
|
||||
|
||||
RuleFor(x => x.Id)
|
||||
.NotEmpty().WithMessage("Id is required")
|
||||
@@ -22,9 +19,9 @@ public class MedicalHistoryUpdateValidation : AbstractValidator<MedicalHistoryUp
|
||||
.NotEmpty().WithMessage("Description is required.");
|
||||
}
|
||||
|
||||
private async Task<bool> BeExistingMedicalHistoryRecord(Guid guid, CancellationToken token)
|
||||
private async Task<bool> BeExistingMedicalHistoryRecord(Guid id, CancellationToken token)
|
||||
{
|
||||
var record = await _medicalHistoryRepository.GetByIdAsync(guid);
|
||||
var record = await _medicalHistoryRepository.GetByIdAsync(id, token);
|
||||
return record != null;
|
||||
}
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
|
||||
namespace Application.Endpoints.MedicalHistories.QuerriesMedicalHistories;
|
||||
|
||||
public class QuerriesMedicalHistoriesHandler(IMedicalHistoryRepository medicalHistoryRepository)
|
||||
{
|
||||
public async Task<BaseResponse> HandleGetAll(CancellationToken token)
|
||||
{
|
||||
var documents = await medicalHistoryRepository.GetAllAsync(token);
|
||||
if (documents.Any())
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.OK,
|
||||
Message = "Retrieved medical histories",
|
||||
Data = documents.ToList()
|
||||
};
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NoContent,
|
||||
Message = "Medical histories not found",
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<BaseResponse> HandleGet(Guid id, CancellationToken token)
|
||||
{
|
||||
var medicalHistory = await medicalHistoryRepository.GetByIdAsync(id, token);
|
||||
if (medicalHistory != null)
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.OK,
|
||||
Message = "Medical history successfully retrieved",
|
||||
Data = medicalHistory
|
||||
};
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NotFound,
|
||||
Message = "Medical history not found in system.",
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<BaseResponse> HandleGetByPatientId(Guid patientId, CancellationToken token)
|
||||
{
|
||||
var medicalHistory = await medicalHistoryRepository.GetByPatientIdAsync(patientId, token);
|
||||
if (medicalHistory != null)
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.OK,
|
||||
Message = "Medical history successfully retrieved",
|
||||
Data = medicalHistory
|
||||
};
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NotFound,
|
||||
Message = "Medical history not found in system.",
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
using Application.Endpoints.MedicalHistories;
|
||||
using Application.Services.Database.MongoDB;
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
|
||||
namespace Application.Endpoints.Patients.DeletePatient;
|
||||
|
||||
public class DeletePatientHandler(
|
||||
IPatientRepository patientRepository,
|
||||
IMedicalHistoryRepository medicalHistoryRepository,
|
||||
IMedicalHistoryMongoDbService medicalHistoryMongoDbService)
|
||||
{
|
||||
public async Task<BaseResponse> Handle(Guid patientId, CancellationToken token)
|
||||
{
|
||||
var patient = await patientRepository.GetByIdAsync(patientId, token);
|
||||
if (patient == null)
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NotFound,
|
||||
Message = "Patient not found.",
|
||||
Data = null
|
||||
};
|
||||
|
||||
await patientRepository.DeleteAsync(patient, token);
|
||||
|
||||
var medicalHistoryList = await medicalHistoryRepository.GetAllAsync(token);
|
||||
foreach (var med in medicalHistoryList)
|
||||
if (med.UserId == patientId)
|
||||
{
|
||||
await medicalHistoryRepository.DeleteAsync(med, token);
|
||||
await medicalHistoryMongoDbService.DeleteByIdAsync<MedicalHistoryAuthorisationModel>(med.Id.ToString(), token);
|
||||
}
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NoContent,
|
||||
Message = null,
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Application.Endpoints.Patients.ModifyPatient;
|
||||
|
||||
public class ModifyPatientCommand
|
||||
{
|
||||
public Guid Id { get; set; } = Guid.Empty;
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public string Email { get; set; } = string.Empty;
|
||||
public string Password { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
using Application.Services.HashingAlgorithms;
|
||||
|
||||
namespace Application.Endpoints.Patients.ModifyPatient;
|
||||
|
||||
public class ModifyPatientHandler(
|
||||
IHashingAlgorithms hashingAlgorithms,
|
||||
IPatientRepository patientRepository,
|
||||
IDoctorRepository doctorRepository,
|
||||
IAdminRepository adminRepository
|
||||
)
|
||||
{
|
||||
public async Task<BaseResponse> Handle(ModifyPatientCommand request, CancellationToken token)
|
||||
{
|
||||
var validation = new PatientProfileValidator(patientRepository, doctorRepository, adminRepository);
|
||||
var validationResult = await validation.ValidateAsync(request, token);
|
||||
|
||||
if (!validationResult.IsValid)
|
||||
{
|
||||
var firstError = validationResult.Errors.FirstOrDefault();
|
||||
var errorCode = int.TryParse(firstError.ErrorCode, out var code) ? code : -1;
|
||||
var errorMessage = firstError.ErrorMessage;
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = errorCode,
|
||||
Message = errorMessage,
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
var newPatient = await patientRepository.GetByIdAsync(request.Id, token);
|
||||
newPatient.SetName(request.Name);
|
||||
newPatient.SetEmail(request.Email);
|
||||
newPatient.SetPassword(hashingAlgorithms.Sha256Algorithm(request.Password));
|
||||
|
||||
await patientRepository.UpdateAsync(newPatient, token);
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NoContent,
|
||||
Message = null,
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
}
|
||||
+16
-8
@@ -1,15 +1,20 @@
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
using FluentValidation;
|
||||
|
||||
namespace Application.Endpoints.Patients.Profile;
|
||||
namespace Application.Endpoints.Patients.ModifyPatient;
|
||||
|
||||
public class PatientProfileValidation : AbstractValidator<PatientProfileDto>
|
||||
public class PatientProfileValidator : AbstractValidator<ModifyPatientCommand>
|
||||
{
|
||||
private readonly IPatientRepository _patientRepository;
|
||||
private readonly IDoctorRepository _doctorRepository;
|
||||
private readonly IAdminRepository _adminRepository;
|
||||
|
||||
public PatientProfileValidation(IPatientRepository patientRepository)
|
||||
public PatientProfileValidator(IPatientRepository patientRepository,
|
||||
IDoctorRepository doctorRepository, IAdminRepository adminRepository)
|
||||
{
|
||||
_patientRepository = patientRepository;
|
||||
_doctorRepository = doctorRepository;
|
||||
_adminRepository = adminRepository;
|
||||
|
||||
RuleFor(x => x.Id)
|
||||
.NotEmpty().WithMessage("Id is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString())
|
||||
@@ -33,15 +38,18 @@ public class PatientProfileValidation : AbstractValidator<PatientProfileDto>
|
||||
.WithErrorCode(HttpStatusCodes.BadRequest.ToString());
|
||||
}
|
||||
|
||||
private async Task<bool> IsPatientRegistered(Guid id, CancellationToken cancellationToken)
|
||||
private async Task<bool> IsPatientRegistered(Guid id, CancellationToken token)
|
||||
{
|
||||
var patient = await _patientRepository.GetByIdAsync(id);
|
||||
var patient = await _patientRepository.GetByIdAsync(id, token);
|
||||
return patient != null;
|
||||
}
|
||||
|
||||
private async Task<bool> BeUniqueEmail(string email, CancellationToken cancellationToken)
|
||||
private async Task<bool> BeUniqueEmail(string email, CancellationToken token)
|
||||
{
|
||||
var patient = await _patientRepository.FindByEmailAsync(email);
|
||||
return patient == null;
|
||||
var patient = await _patientRepository.FindByEmailAsync(email, token);
|
||||
var doctor = await _doctorRepository.FindByEmailAsync(email, token);
|
||||
var admin = await _adminRepository.FindByEmailAsync(email, token);
|
||||
|
||||
return doctor == null && admin == null;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace Application.Endpoints.Patients.Profile;
|
||||
|
||||
public class PatientProfileDto
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Email { get; set; }
|
||||
public string Password { get; set; }
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
using Application.Services.HashingAlgorithms;
|
||||
|
||||
namespace Application.Endpoints.Patients.Profile;
|
||||
|
||||
public class PatientProfileHandler
|
||||
{
|
||||
private readonly IHashingAlgorithms _hashingAlgorithms;
|
||||
private readonly IPatientRepository _patientRepository;
|
||||
|
||||
public PatientProfileHandler(IPatientRepository patientRepository, IHashingAlgorithms hashingAlgorithms)
|
||||
{
|
||||
_patientRepository = patientRepository;
|
||||
_hashingAlgorithms = hashingAlgorithms;
|
||||
}
|
||||
|
||||
public async Task<BaseResponse> HandleGet(Guid id)
|
||||
{
|
||||
var patient = await _patientRepository.GetByIdAsync(id).ConfigureAwait(false);
|
||||
if (patient != null)
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.OK,
|
||||
Message = $"Retrieved patient with id: {id}",
|
||||
Data = patient
|
||||
};
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NotFound,
|
||||
Message = $"Patient with id: {id} not found",
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<BaseResponse> HandleGetAll()
|
||||
{
|
||||
var patients = await _patientRepository.GetAllAsync().ConfigureAwait(false);
|
||||
if (patients.Any())
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.OK,
|
||||
Message = "Retrieved patients",
|
||||
Data = patients.ToList()
|
||||
};
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NoContent,
|
||||
Message = "Patients not found",
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<BaseResponse> HandleUpdate(PatientProfileDto updateDto)
|
||||
{
|
||||
var validation = new PatientProfileValidation(_patientRepository);
|
||||
var validationResult = await validation.ValidateAsync(updateDto);
|
||||
|
||||
if (!validationResult.IsValid)
|
||||
{
|
||||
var firstError = validationResult.Errors.FirstOrDefault();
|
||||
var errorCode = int.TryParse(firstError.ErrorCode, out var code) ? code : -1;
|
||||
var errorMessage = firstError.ErrorMessage;
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = errorCode,
|
||||
Message = errorMessage,
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
var patientToUpdate = await _patientRepository.GetByIdAsync(updateDto.Id);
|
||||
|
||||
patientToUpdate.SetEmail(updateDto.Email);
|
||||
patientToUpdate.SetPassword(_hashingAlgorithms.SHA256Algorithm(updateDto.Password));
|
||||
patientToUpdate.SetName(updateDto.Name);
|
||||
|
||||
await _patientRepository.UpdateAsync(patientToUpdate);
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NoContent,
|
||||
Message = null,
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<BaseResponse> HandleDelete(Guid id)
|
||||
{
|
||||
var patientToDelete = await _patientRepository.GetByIdAsync(id);
|
||||
if (patientToDelete == null)
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NotFound,
|
||||
Message = "Patient not found.",
|
||||
Data = null
|
||||
};
|
||||
|
||||
await _patientRepository.DeleteAsync(patientToDelete);
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NotFound,
|
||||
Message = null,
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
|
||||
namespace Application.Endpoints.Patients.QuerriesPatients;
|
||||
|
||||
public class QuerriesPatientsHandle(IPatientRepository patientRepository)
|
||||
{
|
||||
public async Task<BaseResponse> HandleGet(Guid id, CancellationToken token)
|
||||
{
|
||||
var patient = await patientRepository.GetByIdAsync(id, token);
|
||||
if (patient != null)
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.OK,
|
||||
Message = $"Retrieved patient with id: {id}",
|
||||
Data = patient
|
||||
};
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.NotFound,
|
||||
Message = $"Patient with id: {id} not found",
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<BaseResponse> HandleGetAll(CancellationToken token)
|
||||
{
|
||||
var patients = await patientRepository.GetAllAsync(token);
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.OK,
|
||||
Message = "Retrieved patients",
|
||||
Data = patients.ToList()
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
namespace Application.Endpoints.Patients.Registration;
|
||||
|
||||
public class PatientRegistrationDto
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Email { get; set; }
|
||||
public string Password { get; set; }
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
using Application.Services.HashingAlgorithms;
|
||||
using Core.Entities;
|
||||
|
||||
namespace Application.Endpoints.Patients.Registration;
|
||||
|
||||
public class PatientRegistrationHandler
|
||||
{
|
||||
private readonly IHashingAlgorithms _hashingAlgorithms;
|
||||
private readonly IPatientRepository _patientRepository;
|
||||
|
||||
public PatientRegistrationHandler(IPatientRepository patientRepository, IHashingAlgorithms hashingAlgorithms)
|
||||
{
|
||||
_patientRepository = patientRepository;
|
||||
_hashingAlgorithms = hashingAlgorithms;
|
||||
}
|
||||
|
||||
public async Task<BaseResponse> Handle(PatientRegistrationDto registrationDTO)
|
||||
{
|
||||
var validation = new PatientRegistrationValidation(_patientRepository);
|
||||
var validationResult = await validation.ValidateAsync(registrationDTO);
|
||||
|
||||
if (!validationResult.IsValid)
|
||||
{
|
||||
var firstError = validationResult.Errors.FirstOrDefault();
|
||||
var errorCode = int.TryParse(firstError.ErrorCode, out var code) ? code : -1;
|
||||
var errorMessage = firstError.ErrorMessage;
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = errorCode,
|
||||
Message = errorMessage,
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
var patient = new Patient();
|
||||
patient.SetEmail(registrationDTO.Email);
|
||||
patient.SetName(registrationDTO.Name);
|
||||
patient.SetPassword(_hashingAlgorithms.SHA256Algorithm(registrationDTO.Password));
|
||||
|
||||
await _patientRepository.AddAsync(patient);
|
||||
|
||||
return new BaseResponse
|
||||
{
|
||||
StatusCode = HttpStatusCodes.Created,
|
||||
Message = "Patient registered successfully",
|
||||
Data = patient // Be careful with sending sensitive data like Passwords
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
using Application.Services.Database.PostgreSQL;
|
||||
using FluentValidation;
|
||||
|
||||
namespace Application.Endpoints.Patients.Registration;
|
||||
|
||||
public class PatientRegistrationValidation : AbstractValidator<PatientRegistrationDto>
|
||||
{
|
||||
private readonly IPatientRepository _patientRepository;
|
||||
|
||||
public PatientRegistrationValidation(IPatientRepository patientRepository)
|
||||
{
|
||||
_patientRepository = patientRepository;
|
||||
|
||||
RuleFor(x => x.Email)
|
||||
.NotEmpty().WithMessage("Email is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString())
|
||||
.EmailAddress().WithMessage("Invalid email format.").WithErrorCode(HttpStatusCodes.BadRequest.ToString())
|
||||
.MustAsync(BeUniqueEmail).WithMessage("Email already exists.")
|
||||
.WithErrorCode(HttpStatusCodes.Conflict.ToString());
|
||||
|
||||
|
||||
RuleFor(x => x.Password)
|
||||
.NotEmpty().WithMessage("Password is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString())
|
||||
.MinimumLength(8).WithMessage("Password must be at least 8 characters long.")
|
||||
.WithErrorCode(HttpStatusCodes.BadRequest.ToString());
|
||||
|
||||
RuleFor(x => x.Name)
|
||||
.NotEmpty().WithMessage("Name is required.").WithErrorCode(HttpStatusCodes.BadRequest.ToString())
|
||||
.MinimumLength(3).WithMessage("Name must be at least 3 characters long.")
|
||||
.WithErrorCode(HttpStatusCodes.BadRequest.ToString());
|
||||
}
|
||||
|
||||
private async Task<bool> BeUniqueEmail(string email, CancellationToken cancellationToken)
|
||||
{
|
||||
var pacient = await _patientRepository.FindByEmailAsync(email);
|
||||
return pacient == null;
|
||||
}
|
||||
}
|
||||
@@ -1,55 +1,97 @@
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Application.Endpoints.SicknessPrediction;
|
||||
|
||||
public class PythonScriptRunner
|
||||
{
|
||||
public async Task<BaseResponse> RunPythonScript(string scriptPath, string args)
|
||||
public static async Task<BaseResponse> RunPythonScript(string scriptPath, string args)
|
||||
{
|
||||
var response = new BaseResponse();
|
||||
using (Process process = new Process())
|
||||
var solutionRoot = PathHelper.GetSolutionRoot();
|
||||
var pythonExecutablePath = Path.Combine(solutionRoot, "venv", "Scripts", "python.exe");
|
||||
|
||||
using var process = new Process();
|
||||
process.StartInfo = new ProcessStartInfo(pythonExecutablePath, $"\"{scriptPath}\" \"{args}\"")
|
||||
{
|
||||
process.StartInfo = new ProcessStartInfo("python", $"\"{scriptPath}\" \"{args}\"")
|
||||
{
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true, // Redirect standard error to capture any errors.
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true,
|
||||
};
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
process.Start();
|
||||
|
||||
// Read output and error streams.
|
||||
var output = await process.StandardOutput.ReadToEndAsync();
|
||||
var error = await process.StandardError.ReadToEndAsync();
|
||||
|
||||
process.WaitForExit();
|
||||
try
|
||||
{
|
||||
process.Start();
|
||||
var output = await process.StandardOutput.ReadToEndAsync();
|
||||
var error = await process.StandardError.ReadToEndAsync();
|
||||
await process.WaitForExitAsync();
|
||||
|
||||
if (process.ExitCode == 0) // Assuming exit code 0 as a success.
|
||||
if (process.ExitCode == 0) // Assuming exit code 0 as a success.
|
||||
try
|
||||
{
|
||||
Console.WriteLine(output);
|
||||
response.StatusCode = HttpStatusCodes.OK;
|
||||
response.Message = "Success";
|
||||
response.Data = output;
|
||||
var response = JsonConvert.DeserializeObject<BaseResponsePython>(output);
|
||||
return new BaseResponse()
|
||||
{
|
||||
StatusCode = response.StatusCode,
|
||||
Message = response.Message,
|
||||
Data = response.Data
|
||||
};
|
||||
}
|
||||
else
|
||||
catch (JsonException ex)
|
||||
{
|
||||
Console.WriteLine(error);
|
||||
response.StatusCode = HttpStatusCodes.InternalServerError;
|
||||
response.Message = error; // Using the error output as the message if not successful.
|
||||
response.Data = null;
|
||||
Console.WriteLine($"JSON Error: {ex.Message}");
|
||||
return new BaseResponse { StatusCode = 500, Message = "Error parsing JSON response." };
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
response.StatusCode = HttpStatusCodes.InternalServerError;
|
||||
response.Message = $"An error occurred while executing the Python script: {ex.Message}";
|
||||
response.Data = null;
|
||||
}
|
||||
|
||||
return response;
|
||||
Console.WriteLine(error);
|
||||
return new BaseResponse { StatusCode = 500, Message = error };
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Execution Error: {ex.Message}");
|
||||
return new BaseResponse
|
||||
{ StatusCode = 500, Message = $"An error occurred while executing the Python script: {ex.Message}" };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class PathHelper
|
||||
{
|
||||
public static string GetSolutionRoot()
|
||||
{
|
||||
var currentDir = Directory.GetCurrentDirectory();
|
||||
var solutionRoot = Directory.GetParent(currentDir)?.FullName;
|
||||
|
||||
if (solutionRoot == null)
|
||||
throw new InvalidOperationException("Failed to find the solution root directory.");
|
||||
|
||||
return solutionRoot;
|
||||
}
|
||||
|
||||
public static string GetPythonExecutablePath()
|
||||
{
|
||||
var solutionRoot = GetSolutionRoot();
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
return Path.Combine(solutionRoot, "venv", "Scripts", "python.exe");
|
||||
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
|
||||
return Path.Combine(solutionRoot, "venv", "bin", "python");
|
||||
|
||||
throw new InvalidOperationException("Unsupported operating system.");
|
||||
}
|
||||
}
|
||||
|
||||
public class BaseResponsePython
|
||||
{
|
||||
public int StatusCode { get; set; }
|
||||
public string Message { get; set; } = string.Empty;
|
||||
public List<PredictionData> Data { get; set; } = []; // Correct initialization and make it a property
|
||||
}
|
||||
|
||||
public class PredictionData // Removed abstract if no inheritance is required
|
||||
{
|
||||
public string Disease { get; set; } = string.Empty;
|
||||
public double Probability { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Application.Endpoints.SicknessPrediction;
|
||||
|
||||
public class SicknessPredictionCommand
|
||||
{
|
||||
public string Text { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
namespace Application.Endpoints.SicknessPrediction;
|
||||
|
||||
public class SicknessPredictionDto
|
||||
{
|
||||
public string Text { get; set; }
|
||||
}
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
public class SicknessPredictionHandler
|
||||
{
|
||||
public async Task<BaseResponse> GetPrediction(SicknessPredictionDto dto)
|
||||
public static async Task<BaseResponse> GetPrediction(SicknessPredictionCommand command)
|
||||
{
|
||||
var validation = new SicknessPredictionValidator();
|
||||
var validationResult = await validation.ValidateAsync(dto);
|
||||
var validationResult = await validation.ValidateAsync(command);
|
||||
|
||||
if (!validationResult.IsValid)
|
||||
{
|
||||
@@ -20,13 +20,14 @@ public class SicknessPredictionHandler
|
||||
Data = null
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
var currentDirectory = Directory.GetCurrentDirectory(); // gets the current working directory
|
||||
var applicationDirectory = Path.Combine(Directory.GetParent(currentDirectory)?.FullName, "Application");
|
||||
|
||||
var scriptPath = Path.Combine(applicationDirectory, "Endpoints","SicknessPrediction", "SicknessPredictionScript.py");
|
||||
var scriptPath = Path.Combine(applicationDirectory, "Endpoints", "SicknessPrediction",
|
||||
"SicknessPredictionScript.py");
|
||||
var scriptRunner = new PythonScriptRunner();
|
||||
var result = await scriptRunner.RunPythonScript(scriptPath, dto.Text);
|
||||
var result = await PythonScriptRunner.RunPythonScript(scriptPath, command.Text);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -46,7 +46,6 @@ class DiseasePredictor:
|
||||
self.model.fit(self.X_train, self.y_train) # X_train is a DataFrame with feature names
|
||||
logging.info(f"Training accuracy: {self.model.score(self.X_test, self.y_test):.2f}")
|
||||
|
||||
|
||||
def extract_features(self, text):
|
||||
logging.info("Extracting features from text")
|
||||
|
||||
@@ -118,7 +117,7 @@ class DiseasePredictor:
|
||||
if count == 3:
|
||||
break
|
||||
# Return the JSON object
|
||||
return json.dumps(json_output, indent=4)
|
||||
return json.dumps(json_output)
|
||||
|
||||
|
||||
# Example usage:
|
||||
@@ -127,11 +126,11 @@ if __name__ == "__main__":
|
||||
if len(sys.argv) != 2:
|
||||
logging.error("Incorrect number of arguments provided.")
|
||||
json_output = {
|
||||
"StatusCode": 400,
|
||||
"Message": "Incorrect number of arguments provided.",
|
||||
"Data": []
|
||||
}
|
||||
print(json.dumps(json_output, indent=4))
|
||||
"StatusCode": 400,
|
||||
"Message": "Incorrect number of arguments provided.",
|
||||
"Data": []
|
||||
}
|
||||
print(json.dumps(json_output))
|
||||
sys.exit(1)
|
||||
|
||||
logging.basicConfig(filename='disease_prediction.log', level=logging.INFO,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Application.Endpoints.SicknessPrediction;
|
||||
|
||||
public class SicknessPredictionValidator : AbstractValidator<SicknessPredictionDto>
|
||||
public class SicknessPredictionValidator : AbstractValidator<SicknessPredictionCommand>
|
||||
{
|
||||
public SicknessPredictionValidator()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user