refactor: tweak driver registration endpoint; remove driver update endpoint

This commit is contained in:
cuqmbr 2023-06-04 17:09:23 +03:00
parent 287dccd440
commit 8b9c9ae324
23 changed files with 191 additions and 133 deletions

View File

@ -1,9 +1,12 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Server.Services;
using SharedModels.Requests;
using SharedModels.Requests.Account;
namespace Server.Controllers;
[Authorize]
[Route("api/account")]
[ApiController]
public class AccountController : ControllerBase
@ -41,7 +44,7 @@ public class AccountController : ControllerBase
return Ok();
}
[HttpPost("confirmationEmailCallback")]
[HttpPost("confirmChangeEmail")]
public async Task<IActionResult> ConfirmChangeEmail([FromBody] ConfirmChangeEmailRequest request)
{
var result = await _accountManagementService.ConfirmChangeEmail(request);
@ -67,7 +70,7 @@ public class AccountController : ControllerBase
return Ok();
}
[HttpPost("confirmPhoneNumber")]
[HttpPost("confirmChangePhoneNumber")]
public async Task<IActionResult> ConfirmPhoneNumber([FromBody] ConfirmChangePhoneNumberRequest request)
{
var result = await _accountManagementService.ConfirmPhoneNumberChange(request);

View File

@ -4,6 +4,7 @@ using Microsoft.Extensions.Options;
using Server.Configurations;
using Server.Services;
using SharedModels.Requests;
using SharedModels.Requests.Authentication;
using SharedModels.Responses;
namespace Server.Controllers;

View File

@ -4,6 +4,7 @@ using Newtonsoft.Json;
using Server.Services;
using SharedModels.DataTransferObjects.Model;
using SharedModels.QueryParameters.Objects;
using SharedModels.Requests;
namespace Server.Controllers;
@ -20,17 +21,17 @@ public class DriverController : ControllerBase
}
[Authorize(Policy = "CompanyAccess")]
[HttpPost]
public async Task<IActionResult> AddDriver(CreateDriverDto Driver)
[HttpPost("register")]
public async Task<IActionResult> AddDriver(DriverRegistrationRequest driverRegistrationRequest)
{
var result = await _driverManagementService.AddDriver(Driver);
var result = await _driverManagementService.RegisterDriver(driverRegistrationRequest);
if (!result.isSucceeded)
{
return result.actionResult;
}
return CreatedAtAction(nameof(GetDriver), new {id = result.driver.Id}, result.driver);
return Ok();
}
[Authorize(Policy = "CompanyAccess")]
@ -63,20 +64,6 @@ public class DriverController : ControllerBase
return Ok(result.driver);
}
[Authorize(Policy = "CompanyAccess")]
[HttpPut("{id}")]
public async Task<IActionResult> UpdateDriver(string id, UpdateDriverDto driver)
{
var result = await _driverManagementService.UpdateDriver(id, driver);
if (!result.isSucceeded)
{
return result.actionResult;
}
return Ok(result.driver);
}
[Authorize(Policy = "CompanyAccess")]
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteDriver(string id)

View File

@ -2,6 +2,7 @@ using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Server.Models;
using SharedModels.Requests;
using SharedModels.Requests.Account;
namespace Server.Services;

View File

@ -12,7 +12,7 @@ using Microsoft.IdentityModel.Tokens;
using Server.Configurations;
using Server.Constants;
using Server.Models;
using SharedModels.Requests;
using SharedModels.Requests.Authentication;
using SharedModels.Responses;
using Utils;
@ -55,7 +55,6 @@ public class AuthenticationService : IAuthenticationService
var user = new User
{
UserName = "temp",
FirstName = request.FirstName,
LastName = request.LastName,
Patronymic = request.Patronymic,

View File

@ -9,44 +9,45 @@ using Server.Models;
using SharedModels.DataTransferObjects.Model;
using SharedModels.QueryParameters;
using SharedModels.QueryParameters.Objects;
using SharedModels.Requests;
using SharedModels.Requests.Account;
using Utils;
namespace Server.Services;
public class DriverManagementService : IDriverManagementService
{
private readonly IUserManagementService _userManagementService;
private readonly UserManager<User> _userManager;
private readonly ApplicationDbContext _dbContext;
private readonly IMapper _mapper;
private readonly ISortHelper<ExpandoObject> _userSortHelper;
private readonly IDataShaper<DriverDto> _userDataShaper;
private readonly IPager<ExpandoObject> _pager;
private readonly ISessionUserService _sessionUserService;
private readonly IEmailSenderService _emailSender;
public DriverManagementService(IUserManagementService userManagementService, IMapper mapper,
UserManager<User> userManager, ApplicationDbContext dbContext,
public DriverManagementService( IMapper mapper, UserManager<User> userManager,
ISortHelper<ExpandoObject> userSortHelper, IDataShaper<DriverDto> userDataShaper,
IPager<ExpandoObject> pager, ISessionUserService sessionUserService)
IPager<ExpandoObject> pager, ISessionUserService sessionUserService,
IEmailSenderService emailSenderService)
{
_userManagementService = userManagementService;
_userManager = userManager;
_dbContext = dbContext;
_userSortHelper = userSortHelper;
_userDataShaper = userDataShaper;
_pager = pager;
_sessionUserService = sessionUserService;
_emailSender = emailSenderService;
_mapper = mapper;
_userManager.UserValidators.Clear();
}
public async Task<(bool isSucceeded, IActionResult? actionResult, DriverDto driver)> AddDriver(CreateDriverDto createDriverDto)
public async Task<(bool isSucceeded, IActionResult actionResult)> RegisterDriver(DriverRegistrationRequest request)
{
if (_sessionUserService.GetAuthUserRole() == Identity.Roles.Administrator.ToString())
{
if (createDriverDto.CompanyId == null)
if (request.CompanyId == null)
{
return (false, new BadRequestObjectResult("CompanyId must have a value"), null!);
return (false, new BadRequestObjectResult("CompanyId must have a value"));
}
}
else
@ -54,35 +55,63 @@ public class DriverManagementService : IDriverManagementService
var isAuthUserCompanyOwnerResult = await _sessionUserService.IsAuthUserCompanyOwner();
if (!isAuthUserCompanyOwnerResult.isCompanyOwner)
{
return (false, new UnauthorizedResult(), null!);
return (false, new UnauthorizedResult());
}
createDriverDto.CompanyId = isAuthUserCompanyOwnerResult.companyId;
request.CompanyId = isAuthUserCompanyOwnerResult.companyId;
}
var createUserDto = _mapper.Map<CreateUserDto>(createDriverDto);
createUserDto.Roles = new List<string> { "Driver" };
createUserDto.Password = createDriverDto.Password;
var result = await _userManagementService.AddUser(createUserDto);
if (!result.isSucceeded)
var userWithSameEmail = await _userManager.FindByEmailAsync(request.Email);
if (userWithSameEmail != null)
{
return (false, result.actionResult, null);
return (false, new BadRequestObjectResult("Email is already registered."));
}
var driverDto = _mapper.Map<DriverDto>(result.user);
_dbContext.CompanyDrivers.Add(new CompanyDriver { CompanyId = (int) createDriverDto.CompanyId, DriverId = driverDto.Id });
await _dbContext.SaveChangesAsync();
var userWithSamePhone = await _userManager.Users
.SingleOrDefaultAsync(u => u.PhoneNumber == request.PhoneNumber);
if (userWithSamePhone != null)
{
return (false, new BadRequestObjectResult("Phone is already registered."));
}
driverDto.Roles = result.user.Roles;
var user = new User
{
FirstName = request.FirstName,
LastName = request.LastName,
Patronymic = request.Patronymic,
BirthDate = new DateTime(request.BirthDate.Year, request.BirthDate.Month, request.BirthDate.Day, 0, 0, 0, DateTimeKind.Utc),
Email = request.Email,
PhoneNumber = request.PhoneNumber
};
return (true, null, driverDto);
var createUserResult = await _userManager.CreateAsync(user, request.Password);
if (!createUserResult.Succeeded)
{
return (false, new BadRequestObjectResult(createUserResult.Errors));
}
await _userManager.AddToRoleAsync(user, Identity.Roles.Driver.ToString());
user.Employer = new CompanyDriver { CompanyId = (int)request.CompanyId };
user.Gender = request.Gender;
user.Document = request.Document;
user.DocumentDetails = request.DocumentDetails;
await _userManager.UpdateAsync(user);
var emailMessage = "You have been registered as a driver.\n\n" +
$"Your login: ${request.Email}\nYour password: ${request.Password}";
try { await _emailSender.SendMail(request.Email, "Driver Registration", emailMessage); }
catch (Exception) { /* ignored */ }
return (true, null!);
}
public async Task<(bool isSucceeded, IActionResult? actionResult, IEnumerable<ExpandoObject> drivers, PagingMetadata<ExpandoObject> pagingMetadata)> GetDrivers(CompanyDriverParameters parameters)
public async Task<(bool isSucceeded, IActionResult actionResult, IEnumerable<ExpandoObject> drivers, PagingMetadata<ExpandoObject> pagingMetadata)>
GetDrivers(CompanyDriverParameters parameters)
{
var dbUsers = _userManager.Users.Include(u => u.Employer)
var dbDriverUsers = _userManager.Users.Include(u => u.Employer)
.Where(u => u.Employer != null).AsQueryable();
if (_sessionUserService.GetAuthUserRole() != Identity.Roles.Administrator.ToString())
@ -93,18 +122,18 @@ public class DriverManagementService : IDriverManagementService
return (false, new UnauthorizedResult(), null!, null!);
}
dbUsers = dbUsers.Where(u => u.Employer.CompanyId == result.companyId);
dbDriverUsers = dbDriverUsers.Where(u => u.Employer!.CompanyId == result.companyId);
}
if (!dbUsers.Any())
if (!dbDriverUsers.Any())
{
return (false, new NotFoundResult(), null!, null!);
}
FilterByCompanyId(ref dbUsers, parameters.CompanyId);
SearchByAllUserFields(ref dbUsers, parameters.Search);
FilterByCompanyId(ref dbDriverUsers, parameters.CompanyId);
SearchByAllUserFields(ref dbDriverUsers, parameters.Search);
var userDtos = _mapper.ProjectTo<DriverDto>(dbUsers);
var userDtos = _mapper.ProjectTo<DriverDto>(dbDriverUsers);
var shapedData = _userDataShaper.ShapeData(userDtos, parameters.Fields).AsQueryable();
try
@ -118,16 +147,16 @@ public class DriverManagementService : IDriverManagementService
var pagingMetadata = _pager.ApplyPaging(ref shapedData, parameters.PageNumber, parameters.PageSize);
return (true, null, shapedData, pagingMetadata);
return (true, null!, shapedData, pagingMetadata);
void FilterByCompanyId(ref IQueryable<User> users, int? compnayId)
void FilterByCompanyId(ref IQueryable<User> users, int? companyId)
{
if (!users.Any() || compnayId == null)
if (!users.Any() || companyId == null)
{
return;
}
users = users.Where(u => u.Employer.CompanyId == compnayId);
users = users.Where(u => u.Employer!.CompanyId == companyId);
}
void SearchByAllUserFields(ref IQueryable<User> users, string? search)
@ -137,29 +166,31 @@ public class DriverManagementService : IDriverManagementService
return;
}
users = users.Where(u =>
u.FirstName.ToLower().Contains(search.ToLower()) ||
u.LastName.ToLower().Contains(search.ToLower()) ||
u.Patronymic.ToLower().Contains(search.ToLower()) ||
var t = users.ToArray().Where(u =>
(u.LastName.ToLower() + u.FirstName.ToLower() + u.Patronymic.ToLower()).Contains(search.ToLower()) ||
u.Email.ToLower().Contains(search.ToLower()) ||
u.PhoneNumber.ToLower().Contains(search.ToLower()));
users = t
.AsQueryable();
}
}
public async Task<(bool isSucceeded, IActionResult? actionResult, ExpandoObject driver)> GetDriver(string id, string? fields)
public async Task<(bool isSucceeded, IActionResult actionResult, ExpandoObject driver)>
GetDriver(string driverId, string? fields)
{
if (_sessionUserService.GetAuthUserRole() != Identity.Roles.Administrator.ToString())
{
if (!await _sessionUserService.IsAuthUserCompanyDriver(id))
if (!await _sessionUserService.IsAuthUserCompanyDriver(driverId))
{
return (false, new UnauthorizedResult(), null!);
}
}
var dbUser = await _userManager.Users.Include(u => u.Employer).
FirstOrDefaultAsync(u => u.Id == id);
var dbDriverUser = await _userManager.Users.Include(u => u.Employer).
FirstOrDefaultAsync(u => u.Id == driverId && u.Employer != null);
if (dbUser == null)
if (dbDriverUser == null)
{
return (false, new NotFoundResult(), null!);
}
@ -169,39 +200,24 @@ public class DriverManagementService : IDriverManagementService
fields = CompanyDriverParameters.DefaultFields;
}
var userDto = _mapper.Map<DriverDto>(dbUser);
var userDto = _mapper.Map<DriverDto>(dbDriverUser);
var shapedData = _userDataShaper.ShapeData(userDto, fields);
return (true, null, shapedData);
return (true, null!, shapedData);
}
public async Task<(bool isSucceeded, IActionResult? actionResult, DriverDto driver)> UpdateDriver(string id, UpdateDriverDto updateDriverDto)
public async Task<(bool isSucceed, IActionResult actionResult)> DeleteDriver(string driverId)
{
if (_sessionUserService.GetAuthUserRole() != Identity.Roles.Administrator.ToString())
{
if (!(await _sessionUserService.IsAuthUserCompanyOwner()).isCompanyOwner &&
!await _sessionUserService.IsAuthUserCompanyDriver(id))
{
return (false, new UnauthorizedResult(), null!);
}
}
var updateUserDto = _mapper.Map<UpdateUserDto>(updateDriverDto);
var result = await _userManagementService.UpdateUser(id, updateUserDto);
return (result.isSucceeded, result.actionResult, _mapper.Map<DriverDto>(result.user));
}
public async Task<(bool isSucceed, IActionResult? actionResult)> DeleteDriver(string id)
{
if (_sessionUserService.GetAuthUserRole() != Identity.Roles.Administrator.ToString())
{
if (!await _sessionUserService.IsAuthUserCompanyDriver(id))
if (!await _sessionUserService.IsAuthUserCompanyDriver(driverId))
{
return (false, new UnauthorizedResult());
}
}
return await _userManagementService.DeleteUser(id);
await _userManager.DeleteAsync(await _userManager.FindByIdAsync(driverId));
return (true, null!);
}
}

View File

@ -1,5 +1,6 @@
using Microsoft.AspNetCore.Mvc;
using SharedModels.Requests;
using SharedModels.Requests.Account;
namespace Server.Services;

View File

@ -1,5 +1,6 @@
using Microsoft.AspNetCore.Mvc;
using SharedModels.Requests;
using SharedModels.Requests.Authentication;
using SharedModels.Responses;
namespace Server.Services;

View File

@ -1,22 +1,21 @@
using System.Dynamic;
using Microsoft.AspNetCore.Mvc;
using SharedModels.DataTransferObjects.Model;
using SharedModels.QueryParameters;
using SharedModels.QueryParameters.Objects;
using SharedModels.Requests;
namespace Server.Services;
public interface IDriverManagementService
{
Task<(bool isSucceeded, IActionResult? actionResult, DriverDto driver)> AddDriver(CreateDriverDto createDriverDto);
Task<(bool isSucceeded, IActionResult actionResult)> RegisterDriver(DriverRegistrationRequest request);
Task<(bool isSucceeded, IActionResult? actionResult, IEnumerable<ExpandoObject> drivers, PagingMetadata<ExpandoObject> pagingMetadata)>
Task<(bool isSucceeded, IActionResult actionResult, IEnumerable<ExpandoObject> drivers, PagingMetadata<ExpandoObject> pagingMetadata)>
GetDrivers(CompanyDriverParameters parameters);
Task<(bool isSucceeded, IActionResult? actionResult, ExpandoObject driver)> GetDriver(string id, string? fields);
Task<(bool isSucceeded, IActionResult? actionResult, DriverDto driver)> UpdateDriver(string id, UpdateDriverDto updateDriverDto);
Task<(bool isSucceed, IActionResult? actionResult)> DeleteDriver(string id);
Task<(bool isSucceeded, IActionResult actionResult, ExpandoObject driver)>
GetDriver(string driverId, string? fields);
Task<(bool isSucceed, IActionResult actionResult)> DeleteDriver(string driverId);
}

View File

@ -1,18 +1,45 @@
using System.ComponentModel.DataAnnotations;
using Utils;
namespace SharedModels.DataTransferObjects.Model;
public class DriverDto : UserDto
public class DriverDto : UpdateDriverDto
{
public string FullName { get; set; } = null!;
public bool EmailConfirmed { get; set; }
public bool PhoneNumberConfirmed { get; set; }
}
public class UpdateDriverDto
{
[Required]
public string Id { get; set; } = null!;
[Required]
public string FirstName { get; set; } = null!;
[Required]
public string LastName { get; set; } = null!;
[Required]
public string Patronymic { get; set; } = null!;
[Required]
public Identity.Gender Gender { get; set; }
[Required]
[DataType(DataType.Date)]
public DateTime BirthDate { get; set; }
[Required]
public Identity.Document Document { get; set; }
[Required]
public string DocumentDetails { get; set; } = null!;
[Required]
public string Email { get; set; } = null!;
[Required]
public string PhoneNumber { get; set; } = null!;
[Required]
public int CompanyId { get; set; }
}
public class CreateDriverDto : CreateUserDto
{
public int? CompanyId { get; set; }
public override IList<string>? Roles { get; set; }
}
public class UpdateDriverDto : UpdateUserDto
{
public override IList<string>? Roles { get; set; }
}

View File

@ -1,6 +1,6 @@
using System.ComponentModel.DataAnnotations;
namespace SharedModels.Requests;
namespace SharedModels.Requests.Account;
public class ChangeEmailRequest
{

View File

@ -1,7 +1,7 @@
using System.ComponentModel.DataAnnotations;
using Utils;
namespace SharedModels.Requests;
namespace SharedModels.Requests.Account;
public class ChangeInformationRequest
{

View File

@ -1,6 +1,6 @@
using System.ComponentModel.DataAnnotations;
namespace SharedModels.Requests;
namespace SharedModels.Requests.Account;
public class ChangePasswordRequest
{

View File

@ -1,6 +1,6 @@
using System.ComponentModel.DataAnnotations;
namespace SharedModels.Requests;
namespace SharedModels.Requests.Account;
public class ChangePhoneNumberRequest
{

View File

@ -1,6 +1,6 @@
using System.ComponentModel.DataAnnotations;
namespace SharedModels.Requests;
namespace SharedModels.Requests.Account;
public class ConfirmChangeEmailRequest : ChangeEmailRequest
{

View File

@ -1,6 +1,6 @@
using System.ComponentModel.DataAnnotations;
namespace SharedModels.Requests;
namespace SharedModels.Requests.Account;
public class ConfirmChangePhoneNumberRequest : ChangePhoneNumberRequest
{

View File

@ -1,6 +1,6 @@
using System.ComponentModel.DataAnnotations;
namespace SharedModels.Requests;
namespace SharedModels.Requests.Authentication;
public class AuthenticationRequest
{

View File

@ -1,6 +1,6 @@
using System.ComponentModel.DataAnnotations;
namespace SharedModels.Requests;
namespace SharedModels.Requests.Authentication;
public class ConfirmRegistrationEmailRequest
{

View File

@ -1,6 +1,6 @@
using System.ComponentModel.DataAnnotations;
namespace SharedModels.Requests;
namespace SharedModels.Requests.Authentication;
public class ConfirmRegistrationPhoneNumberRequest
{

View File

@ -1,4 +1,4 @@
namespace SharedModels.Requests;
namespace SharedModels.Requests.Authentication;
public class GoogleAuthenticationRequest
{

View File

@ -1,27 +1,27 @@
using System.ComponentModel.DataAnnotations;
namespace SharedModels.Requests;
namespace SharedModels.Requests.Authentication;
public class RegistrationRequest
{
[Required(ErrorMessage = "Firstname is required")]
[Required]
public string FirstName { get; set; } = null!;
[Required(ErrorMessage = "Lastname is required")]
[Required]
public string LastName { get; set; } = null!;
[Required(ErrorMessage = "Patronymic is required")]
[Required]
public string Patronymic { get; set; } = null!;
[Required(ErrorMessage = "Email is required")]
[Required]
[EmailAddress]
public string Email { get; set; } = null!;
[Required(ErrorMessage = "Phone number is required")]
[Required]
[Phone]
public string PhoneNumber { get; set; } = null!;
[Required(ErrorMessage = "Password is required")]
[Required]
[DataType(DataType.Password)]
public string Password { get; set; } = null!;
}

View File

@ -1,4 +1,4 @@
namespace SharedModels.Requests;
namespace SharedModels.Requests.Authentication;
public class RevokeRefreshTokenRequest
{

View File

@ -0,0 +1,23 @@
using System.ComponentModel.DataAnnotations;
using SharedModels.Requests.Authentication;
using Utils;
namespace SharedModels.Requests;
public class DriverRegistrationRequest : RegistrationRequest
{
public int? CompanyId { get; set; }
[Required]
public Identity.Gender Gender { get; set; }
[Required]
[DataType(DataType.Date)]
public DateTime BirthDate { get; set; }
[Required]
public Identity.Document Document { get; set; }
[Required]
public string DocumentDetails { get; set; } = null!;
}