diff --git a/src/Booking/Booking.Application/Appointments/Queries/GetAppointmentById/GetAppointmentByIdQueryHandler.cs b/src/Booking/Booking.Application/Appointments/Queries/GetAppointmentById/GetAppointmentByIdQueryHandler.cs index d824e41..e71f02c 100644 --- a/src/Booking/Booking.Application/Appointments/Queries/GetAppointmentById/GetAppointmentByIdQueryHandler.cs +++ b/src/Booking/Booking.Application/Appointments/Queries/GetAppointmentById/GetAppointmentByIdQueryHandler.cs @@ -21,6 +21,8 @@ public async Task Handle( .AsNoTracking() .Include(a => a.Doctor) .ThenInclude(d => d.Specialty) + .Include(b => b.Doctor) + .ThenInclude(d => d.ApplicationUser) .Include(a => a.Patient) .ThenInclude(p => p.ApplicationUser) .Include(a => a.Attachments) diff --git a/src/Booking/Booking.Application/Common/Exceptions/ForbiddenAccessException.cs b/src/Booking/Booking.Application/Common/Exceptions/ForbiddenAccessException.cs new file mode 100644 index 0000000..7f8e532 --- /dev/null +++ b/src/Booking/Booking.Application/Common/Exceptions/ForbiddenAccessException.cs @@ -0,0 +1,18 @@ +namespace Booking.Application.Doctors.Command.DeleteDoctor +{ + [Serializable] + internal class ForbiddenAccessException : Exception + { + public ForbiddenAccessException() + { + } + + public ForbiddenAccessException(string? message) : base(message) + { + } + + public ForbiddenAccessException(string? message, Exception? innerException) : base(message, innerException) + { + } + } +} \ No newline at end of file diff --git a/src/Booking/Booking.Application/Doctors/Command/CreateDoctor/CreateDoctorCommandHandler.cs b/src/Booking/Booking.Application/Doctors/Command/CreateDoctor/CreateDoctorCommandHandler.cs index f104f59..fb7e905 100644 --- a/src/Booking/Booking.Application/Doctors/Command/CreateDoctor/CreateDoctorCommandHandler.cs +++ b/src/Booking/Booking.Application/Doctors/Command/CreateDoctor/CreateDoctorCommandHandler.cs @@ -19,15 +19,13 @@ public async Task Handle( CreateDoctorCommand createDoctor, CancellationToken cancellationToken) { - var user = new ApplicationUser - { - UserName = createDoctor.Email, - Email = createDoctor.Email, - FirstName = createDoctor.Name, - LastName = createDoctor.Lastname, - PhoneNumber = createDoctor.PhoneNumber, - EmailConfirmed = true, - }; + var user = ApplicationUser.CreateDoctor + ( + email: createDoctor.Email, + firstName: createDoctor.Name, + lastName: createDoctor.Lastname, + phoneNumber: createDoctor.PhoneNumber + ); (await _userManager.CreateAsync(user, createDoctor.Password)) .EnsureSucceeded("CreateDoctor"); diff --git a/src/Booking/Booking.Application/Doctors/Command/DeleteDoctor/DeleteDoctorCommandHandler.cs b/src/Booking/Booking.Application/Doctors/Command/DeleteDoctor/DeleteDoctorCommandHandler.cs index 5a55174..5feeda3 100644 --- a/src/Booking/Booking.Application/Doctors/Command/DeleteDoctor/DeleteDoctorCommandHandler.cs +++ b/src/Booking/Booking.Application/Doctors/Command/DeleteDoctor/DeleteDoctorCommandHandler.cs @@ -1,5 +1,6 @@ using Booking.Application.Common.Exceptions; using Booking.Application.Common.Interfaces; +using Booking.Domain.Constants; using Booking.Domain.Entities; using MediatR; using Microsoft.EntityFrameworkCore; @@ -8,20 +9,30 @@ namespace Booking.Application.Doctors.Command.DeleteDoctor { public class DeleteDoctorCommandHandler( IBookingDbContext context, - IIdentityService identityService) + IIdentityService identityService, + ICurrentUserService userService) : IRequestHandler { private readonly IBookingDbContext _context = context; private readonly IIdentityService _identityService = identityService; + private readonly ICurrentUserService _currentUserService = userService; public async Task Handle( DeleteDoctorCommand request, CancellationToken cancellationToken) { + var currentUser = _currentUserService.UserId; + + if (string.IsNullOrEmpty(currentUser)) + throw new UnauthorizedAccessException("User is not authenticated."); + + if (!await _identityService.IsInRoleAsync(currentUser, Roles.Admin)) + throw new ForbiddenAccessException("Only administrators can delete doctors"); + var doctor = await _context.Doctors - .Include(d => d.Appointments) - .FirstOrDefaultAsync(d => d.Id == request.DoctorId, cancellationToken) - ?? throw new NotFoundException(nameof(Doctor), request.DoctorId); + .Include(d => d.Appointments) + .FirstOrDefaultAsync(d => d.Id == request.DoctorId, cancellationToken) + ?? throw new NotFoundException(nameof(Doctor), request.DoctorId); var hasActiveAppointments = doctor.Appointments diff --git a/src/Booking/Booking.Application/Doctors/Command/UpdateDoctor/UpdateDoctorCommandHandler.cs b/src/Booking/Booking.Application/Doctors/Command/UpdateDoctor/UpdateDoctorCommandHandler.cs index b044f04..33c0017 100644 --- a/src/Booking/Booking.Application/Doctors/Command/UpdateDoctor/UpdateDoctorCommandHandler.cs +++ b/src/Booking/Booking.Application/Doctors/Command/UpdateDoctor/UpdateDoctorCommandHandler.cs @@ -35,7 +35,7 @@ public async Task Handle( var currentUser = await _userManager.FindByIdAsync(currentDoctorId); var isAdmin = currentUser != null && await _userManager.IsInRoleAsync(currentUser, Roles.Admin); - if (!isOwner && isAdmin) + if (!isOwner && !isAdmin) throw new UnauthorizedAccessException("You can only edit your own profile."); doctor.UpdateProfile( @@ -45,9 +45,10 @@ public async Task Handle( request.IsActive, request.ConsultationFee); - doctor.ApplicationUser.FirstName = request.Name; - doctor.ApplicationUser.LastName = request.Lastname; - doctor.ApplicationUser.PhoneNumber = request.PhoneNumber; + doctor.ApplicationUser.UpdatePersonalInfo( + request.Name, + request.Lastname, + request.PhoneNumber); await _dbContext.SaveChangesAsync(cancellationToken); diff --git a/src/Booking/Booking.Application/Identity/Commands/RegisterUser/RegisterUserCommandHandler.cs b/src/Booking/Booking.Application/Identity/Commands/RegisterUser/RegisterUserCommandHandler.cs index 4e43be2..b49ac4a 100644 --- a/src/Booking/Booking.Application/Identity/Commands/RegisterUser/RegisterUserCommandHandler.cs +++ b/src/Booking/Booking.Application/Identity/Commands/RegisterUser/RegisterUserCommandHandler.cs @@ -20,16 +20,14 @@ public async Task Handle( RegisterUserCommand request, CancellationToken cancellationToken) { - var user = new ApplicationUser - { - FirstName = request.UserName, - LastName = request.UserSurname, - Email = request.UserEmail, - UserName = request.UserEmail, - PhoneNumber = request.PhoneNumber, - Address = request.Address, - EmailConfirmed = true - }; + var user = ApplicationUser.CreatePatient + ( + firstName: request.UserName, + lastName: request.UserSurname, + email: request.UserEmail, + phoneNumber: request.PhoneNumber ?? string.Empty, + adress: request.Address ?? string.Empty + ); var createResult = await _userManager.CreateAsync(user, request.UserPassword); diff --git a/src/Booking/Booking.Domain/Entities/ApplicationUser.cs b/src/Booking/Booking.Domain/Entities/ApplicationUser.cs index 9def1c5..8e69ec5 100644 --- a/src/Booking/Booking.Domain/Entities/ApplicationUser.cs +++ b/src/Booking/Booking.Domain/Entities/ApplicationUser.cs @@ -4,12 +4,75 @@ namespace Booking.Domain.Entities { public class ApplicationUser : IdentityUser { - public string FirstName { get; set; } = string.Empty; - public string LastName { get; set; } = string.Empty; - public string? PhotoUrl { get; set; } - public string? Address { get; set; } + public string FirstName { get; private set; } + public string LastName { get; private set; } + public string? PhotoUrl { get; private set; } + public string? Address { get; private set; } - public virtual Patient? PatientProfile { get; set; } - public virtual Doctor? DoctorProfile { get; set; } + public virtual Patient? PatientProfile { get; private set; } + public virtual Doctor? DoctorProfile { get; private set; } + + private ApplicationUser() { } + + public ApplicationUser( + string firstName, + string lastName, + string address) + { + FirstName = firstName; + LastName = lastName; + Address = address; + } + + public static ApplicationUser CreateDoctor( + string email, + string firstName, + string lastName, + string phoneNumber) + { + return new ApplicationUser + { + UserName = email, + Email = email, + FirstName = firstName, + LastName = lastName, + PhoneNumber = phoneNumber, + EmailConfirmed = true + }; + } + + public void UpdatePersonalInfo( + string name, + string lastname, + string? phoneNumber) + { + if (string.IsNullOrEmpty(name)) + throw new ArgumentException("Name cannot be empty."); + if (string.IsNullOrEmpty(lastname)) + throw new ArgumentException("Last name cannot be empty."); + + FirstName = name; + LastName = lastname; + PhoneNumber = phoneNumber; + } + + public static ApplicationUser CreatePatient( + string firstName, + string lastName, + string email, + string phoneNumber, + string adress) + { + return new ApplicationUser + { + UserName = email, + Email = email, + FirstName = firstName, + LastName = lastName, + PhoneNumber = phoneNumber, + Address = adress, + EmailConfirmed = true + }; + } } }