feat: add account management functionality
This commit is contained in:
parent
5fecec2d3e
commit
287dccd440
1
.gitignore
vendored
1
.gitignore
vendored
@ -9,6 +9,7 @@
|
|||||||
*.user
|
*.user
|
||||||
*.userosscache
|
*.userosscache
|
||||||
*.sln.docstates
|
*.sln.docstates
|
||||||
|
*.Development.json
|
||||||
|
|
||||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||||
*.userprefs
|
*.userprefs
|
||||||
|
@ -35,6 +35,7 @@ public class MapperInitializer : Profile
|
|||||||
CreateMap<Address, InCityAddressDto>().ReverseMap();
|
CreateMap<Address, InCityAddressDto>().ReverseMap();
|
||||||
CreateMap<Address, CreateAddressInRouteAddress>().ReverseMap();
|
CreateMap<Address, CreateAddressInRouteAddress>().ReverseMap();
|
||||||
CreateMap<Address, AddressInRouteAddress>().ReverseMap();
|
CreateMap<Address, AddressInRouteAddress>().ReverseMap();
|
||||||
|
CreateMap<Address, InTicketAddress>().ReverseMap();
|
||||||
|
|
||||||
CreateMap<RouteAddress, RouteAddressDto>()
|
CreateMap<RouteAddress, RouteAddressDto>()
|
||||||
.ForMember(d => d.AddressName, opt => opt.MapFrom(src => src.Address.Name))
|
.ForMember(d => d.AddressName, opt => opt.MapFrom(src => src.Address.Name))
|
||||||
@ -107,9 +108,6 @@ public class MapperInitializer : Profile
|
|||||||
CreateMap<User, StrippedUserDto>().ReverseMap();
|
CreateMap<User, StrippedUserDto>().ReverseMap();
|
||||||
|
|
||||||
CreateMap<User, DriverDto>().ForMember(d => d.CompanyId, o => o.MapFrom(s => s.Employer.CompanyId));
|
CreateMap<User, DriverDto>().ForMember(d => d.CompanyId, o => o.MapFrom(s => s.Employer.CompanyId));
|
||||||
CreateMap<UserDto, DriverDto>().ReverseMap();
|
|
||||||
CreateMap<CreateUserDto, CreateDriverDto>().ReverseMap();
|
|
||||||
CreateMap<CreateDriverDto, UpdateDriverDto>().ReverseMap();
|
|
||||||
|
|
||||||
CreateMap<RouteAddressDetails, RouteAddressDetailsInVehicleEnrollmentDto>().ReverseMap();
|
CreateMap<RouteAddressDetails, RouteAddressDetailsInVehicleEnrollmentDto>().ReverseMap();
|
||||||
CreateMap<RouteAddressDetails, CreateRouteAddressDetailsInVehicleEnrollmentDto>().ReverseMap();
|
CreateMap<RouteAddressDetails, CreateRouteAddressDetailsInVehicleEnrollmentDto>().ReverseMap();
|
||||||
|
95
Server/Controllers/AccountController.cs
Normal file
95
Server/Controllers/AccountController.cs
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Server.Services;
|
||||||
|
using SharedModels.Requests;
|
||||||
|
|
||||||
|
namespace Server.Controllers;
|
||||||
|
|
||||||
|
[Route("api/account")]
|
||||||
|
[ApiController]
|
||||||
|
public class AccountController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly IAccountManagementService _accountManagementService;
|
||||||
|
|
||||||
|
public AccountController(IAccountManagementService accountManagementService)
|
||||||
|
{
|
||||||
|
_accountManagementService = accountManagementService;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("changeInformation")]
|
||||||
|
public async Task<IActionResult> ChangeInformation([FromBody] ChangeInformationRequest request)
|
||||||
|
{
|
||||||
|
var result = await _accountManagementService.ChangeInformation(request);
|
||||||
|
|
||||||
|
if (!result.isSucceed)
|
||||||
|
{
|
||||||
|
return result.actionResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("changeEmail")]
|
||||||
|
public async Task<IActionResult> ChangeEmail([FromBody] ChangeEmailRequest request)
|
||||||
|
{
|
||||||
|
var result = await _accountManagementService.ChangeEmail(request);
|
||||||
|
|
||||||
|
if (!result.isSucceed)
|
||||||
|
{
|
||||||
|
return result.actionResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("confirmationEmailCallback")]
|
||||||
|
public async Task<IActionResult> ConfirmChangeEmail([FromBody] ConfirmChangeEmailRequest request)
|
||||||
|
{
|
||||||
|
var result = await _accountManagementService.ConfirmChangeEmail(request);
|
||||||
|
|
||||||
|
if (!result.isSucceed)
|
||||||
|
{
|
||||||
|
return result.actionResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("changePhoneNumber")]
|
||||||
|
public async Task<IActionResult> ChangePhoneNumber([FromBody] ChangePhoneNumberRequest request)
|
||||||
|
{
|
||||||
|
var result = await _accountManagementService.ChangePhoneNumber(request);
|
||||||
|
|
||||||
|
if (!result.isSucceed)
|
||||||
|
{
|
||||||
|
return result.actionResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("confirmPhoneNumber")]
|
||||||
|
public async Task<IActionResult> ConfirmPhoneNumber([FromBody] ConfirmChangePhoneNumberRequest request)
|
||||||
|
{
|
||||||
|
var result = await _accountManagementService.ConfirmPhoneNumberChange(request);
|
||||||
|
|
||||||
|
if (!result.isSucceed)
|
||||||
|
{
|
||||||
|
return result.actionResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("changePassword")]
|
||||||
|
public async Task<IActionResult> ChangePassword([FromBody] ChangePasswordRequest request)
|
||||||
|
{
|
||||||
|
var result = await _accountManagementService.ChangePassword(request);
|
||||||
|
|
||||||
|
if (!result.isSucceed)
|
||||||
|
{
|
||||||
|
return result.actionResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
}
|
@ -22,30 +22,42 @@ public class AuthenticationController : ControllerBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("register")]
|
[HttpPost("register")]
|
||||||
public async Task<IActionResult> RegisterAsync([FromBody] RegistrationRequest registerRequest)
|
public async Task<IActionResult> RegisterAsync([FromBody] RegistrationRequest request)
|
||||||
{
|
{
|
||||||
var (succeeded, message) = await _authService.RegisterAsync(registerRequest);
|
var result = await _authService.Register(request);
|
||||||
|
|
||||||
if (!succeeded)
|
if (!result.succeeded)
|
||||||
{
|
{
|
||||||
return BadRequest(new ResponseBase {Message = message});
|
return result.actionResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(new ResponseBase{ Message = message });
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("confirmEmail")]
|
[HttpPost("confirmEmail")]
|
||||||
public async Task<IActionResult> ConfirmEmailAsync([FromQuery] string email, [FromQuery] string token,
|
public async Task<IActionResult> ConfirmEmail([FromBody] ConfirmRegistrationEmailRequest request)
|
||||||
[FromQuery] string redirectionUrl)
|
|
||||||
{
|
{
|
||||||
var (succeeded, message) = await _authService.ConfirmEmailAsync(email, token);
|
var result = await _authService.ConfirmRegistrationEmail(request);
|
||||||
|
|
||||||
if (!succeeded)
|
if (!result.succeeded)
|
||||||
{
|
{
|
||||||
return BadRequest(new ResponseBase {Message = message});
|
return result.actionResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("confirmPhoneNumber")]
|
||||||
|
public async Task<IActionResult> ConfirmPhoneNumber([FromBody] ConfirmRegistrationPhoneNumberRequest request)
|
||||||
|
{
|
||||||
|
var result = await _authService.ConfirmRegistrationPhoneNumber(request);
|
||||||
|
|
||||||
return Redirect(redirectionUrl);
|
if (!result.succeeded)
|
||||||
|
{
|
||||||
|
return result.actionResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("authenticate")]
|
[HttpPost("authenticate")]
|
||||||
|
@ -30,8 +30,7 @@ public class SeedData
|
|||||||
var adminUser = new User
|
var adminUser = new User
|
||||||
{
|
{
|
||||||
FirstName = "user", LastName = "user", Patronymic = "user",
|
FirstName = "user", LastName = "user", Patronymic = "user",
|
||||||
Email = "admin@autobus.com",
|
Email = "admin@autobus.com", EmailConfirmed = true
|
||||||
EmailConfirmed = true,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
await userManager.CreateAsync(adminUser, Identity.DefaultPassword);
|
await userManager.CreateAsync(adminUser, Identity.DefaultPassword);
|
||||||
@ -41,7 +40,7 @@ public class SeedData
|
|||||||
|
|
||||||
companyUser = new User
|
companyUser = new User
|
||||||
{
|
{
|
||||||
FirstName = "user", LastName = "user", Patronymic = "user",
|
FirstName = "Firstname", LastName = "Lastname", Patronymic = "Patronymic",
|
||||||
Email = "company@autobus.com",
|
Email = "company@autobus.com",
|
||||||
EmailConfirmed = true
|
EmailConfirmed = true
|
||||||
};
|
};
|
||||||
@ -54,8 +53,11 @@ public class SeedData
|
|||||||
driverUser = new User
|
driverUser = new User
|
||||||
{
|
{
|
||||||
FirstName = "user", LastName = "user", Patronymic = "user",
|
FirstName = "user", LastName = "user", Patronymic = "user",
|
||||||
Email = "driver@autobus.com",
|
Email = "driver@autobus.com", EmailConfirmed = true,
|
||||||
EmailConfirmed = true
|
PhoneNumber = "+380951935723", PhoneNumberConfirmed = true,
|
||||||
|
BirthDate = DateTime.Now.ToUniversalTime(),
|
||||||
|
Document = Identity.Document.Passport, DocumentDetails = "Some details",
|
||||||
|
Gender = Identity.Gender.Male
|
||||||
};
|
};
|
||||||
|
|
||||||
await userManager.CreateAsync(driverUser, Identity.DefaultPassword);
|
await userManager.CreateAsync(driverUser, Identity.DefaultPassword);
|
||||||
@ -66,8 +68,7 @@ public class SeedData
|
|||||||
var defaultUser = new User
|
var defaultUser = new User
|
||||||
{
|
{
|
||||||
FirstName = "user", LastName = "user", Patronymic = "user",
|
FirstName = "user", LastName = "user", Patronymic = "user",
|
||||||
Email = "user@autobus.com",
|
Email = "user@autobus.com", EmailConfirmed = true
|
||||||
EmailConfirmed = true
|
|
||||||
};
|
};
|
||||||
|
|
||||||
await userManager.CreateAsync(defaultUser, Identity.DefaultPassword);
|
await userManager.CreateAsync(defaultUser, Identity.DefaultPassword);
|
||||||
|
@ -107,6 +107,7 @@ services.AddAutoMapper(typeof(MapperInitializer));
|
|||||||
|
|
||||||
services.AddScoped<IEmailSenderService, EmailSenderService>();
|
services.AddScoped<IEmailSenderService, EmailSenderService>();
|
||||||
services.AddScoped<IAuthenticationService, AuthenticationService>();
|
services.AddScoped<IAuthenticationService, AuthenticationService>();
|
||||||
|
services.AddScoped<IAccountManagementService, AccountManagementService>();
|
||||||
|
|
||||||
services.AddScoped<ISessionUserService, SessionUserService>();
|
services.AddScoped<ISessionUserService, SessionUserService>();
|
||||||
|
|
||||||
|
130
Server/Services/AccountManagementService.cs
Normal file
130
Server/Services/AccountManagementService.cs
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Server.Models;
|
||||||
|
using SharedModels.Requests;
|
||||||
|
|
||||||
|
namespace Server.Services;
|
||||||
|
|
||||||
|
public class AccountManagementService : IAccountManagementService
|
||||||
|
{
|
||||||
|
private readonly IEmailSenderService _emailSender;
|
||||||
|
private readonly UserManager<User> _userManager;
|
||||||
|
private readonly ISessionUserService _sessionUserService;
|
||||||
|
|
||||||
|
public AccountManagementService(IEmailSenderService emailSender, UserManager<User> userManager,
|
||||||
|
ISessionUserService sessionUserService)
|
||||||
|
{
|
||||||
|
_emailSender = emailSender;
|
||||||
|
_userManager = userManager;
|
||||||
|
_sessionUserService = sessionUserService;
|
||||||
|
|
||||||
|
_userManager.UserValidators.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<(bool isSucceed, IActionResult actionResult)> ChangeInformation(ChangeInformationRequest request)
|
||||||
|
{
|
||||||
|
var dbUser = await _userManager.FindByIdAsync(_sessionUserService.GetAuthUserId());
|
||||||
|
|
||||||
|
dbUser.FirstName = request.FistName;
|
||||||
|
dbUser.LastName = request.LastName;
|
||||||
|
dbUser.Patronymic = request.Patronymic;
|
||||||
|
dbUser.BirthDate = new DateTime(request.BirthDate.Year, request.BirthDate.Month, request.BirthDate.Day, 0, 0, 0, DateTimeKind.Utc);
|
||||||
|
dbUser.Gender = request.Gender;
|
||||||
|
|
||||||
|
await _userManager.UpdateAsync(dbUser);
|
||||||
|
|
||||||
|
return (true, null!);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<(bool isSucceed, IActionResult actionResult)> ChangeEmail(ChangeEmailRequest request)
|
||||||
|
{
|
||||||
|
var dbUser = await _userManager.FindByIdAsync(_sessionUserService.GetAuthUserId());
|
||||||
|
|
||||||
|
if (dbUser.Email.ToLower() == request.NewEmail.ToLower())
|
||||||
|
{
|
||||||
|
return (false, new BadRequestObjectResult("You must specify a new email"));
|
||||||
|
}
|
||||||
|
|
||||||
|
var changeEmailToken = await _userManager.GenerateChangeEmailTokenAsync(dbUser, request.NewEmail);
|
||||||
|
|
||||||
|
var securityMessage =
|
||||||
|
$"Someone is trying to change email address of your account to {request.NewEmail}. " +
|
||||||
|
"If it is not you please follow account recovery procedure.";
|
||||||
|
var confirmationMessage =
|
||||||
|
"Someone changed account email to your address.\n" +
|
||||||
|
$"Here is your confirmation code: {changeEmailToken}\n\n" +
|
||||||
|
"If this was not you, please ignore this message.";
|
||||||
|
|
||||||
|
try { await _emailSender.SendMail(dbUser.Email, "Security alert", securityMessage); }
|
||||||
|
catch (Exception) { /* ignored */ }
|
||||||
|
|
||||||
|
try { await _emailSender.SendMail(request.NewEmail, "Change email confirmation", confirmationMessage); }
|
||||||
|
catch (Exception) { /* ignored */ }
|
||||||
|
|
||||||
|
return (true, null!);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<(bool isSucceed, IActionResult actionResult)> ConfirmChangeEmail(ConfirmChangeEmailRequest request)
|
||||||
|
{
|
||||||
|
var dbUser = await _userManager.FindByIdAsync(_sessionUserService.GetAuthUserId());
|
||||||
|
|
||||||
|
var result = await _userManager.ChangeEmailAsync(dbUser, request.NewEmail, request.Token);
|
||||||
|
if (!result.Succeeded)
|
||||||
|
{
|
||||||
|
return (false, new BadRequestObjectResult($"Error confirming email change {request.NewEmail}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return (true, null!);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<(bool isSucceed, IActionResult actionResult)> ChangePhoneNumber(ChangePhoneNumberRequest request)
|
||||||
|
{
|
||||||
|
var dbUser = await _userManager.FindByIdAsync(_sessionUserService.GetAuthUserId());
|
||||||
|
|
||||||
|
var changePhoneNumberToken = await _userManager.GenerateChangePhoneNumberTokenAsync(dbUser, request.PhoneNumber);
|
||||||
|
|
||||||
|
var securityMessage =
|
||||||
|
$"Someone is trying to change phone number of your account to {request.PhoneNumber}. " +
|
||||||
|
"If it is not you please follow account recovery procedure.";
|
||||||
|
|
||||||
|
try { await _emailSender.SendMail(dbUser.Email, "Security alert", securityMessage); }
|
||||||
|
catch (Exception) { /* ignored */ }
|
||||||
|
|
||||||
|
// TODO: Send sms message to new phone number
|
||||||
|
|
||||||
|
return (true, null!);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<(bool isSucceed, IActionResult actionResult)> ConfirmPhoneNumberChange(ConfirmChangePhoneNumberRequest request)
|
||||||
|
{
|
||||||
|
var dbUser = await _userManager.FindByIdAsync(_sessionUserService.GetAuthUserId());
|
||||||
|
|
||||||
|
var result = await _userManager.ChangePhoneNumberAsync(dbUser, request.PhoneNumber, request.Token);
|
||||||
|
if (!result.Succeeded)
|
||||||
|
{
|
||||||
|
return (false, new BadRequestObjectResult(result.Errors));
|
||||||
|
}
|
||||||
|
|
||||||
|
return (true, null!);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<(bool isSucceed, IActionResult actionResult)> ChangePassword(ChangePasswordRequest request)
|
||||||
|
{
|
||||||
|
var dbUser = await _userManager.FindByIdAsync(_sessionUserService.GetAuthUserId());
|
||||||
|
|
||||||
|
if (!await _userManager.CheckPasswordAsync(dbUser, request.CurrentPassword))
|
||||||
|
{
|
||||||
|
return (false, new BadRequestObjectResult("Invalid current password"));
|
||||||
|
}
|
||||||
|
|
||||||
|
await _userManager.ChangePasswordAsync(dbUser, request.CurrentPassword, request.NewPassword);
|
||||||
|
|
||||||
|
var securityMessage = "Someone is changed your account password." +
|
||||||
|
"If this was not you please follow account recovery procedure.";
|
||||||
|
|
||||||
|
try { await _emailSender.SendMail(dbUser.Email, "Security alert", securityMessage); }
|
||||||
|
catch (Exception) { /* ignored */ }
|
||||||
|
|
||||||
|
return (true, null!);
|
||||||
|
}
|
||||||
|
}
|
@ -5,6 +5,7 @@ using System.Security.Cryptography;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using Google.Apis.Auth;
|
using Google.Apis.Auth;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using Microsoft.IdentityModel.Tokens;
|
using Microsoft.IdentityModel.Tokens;
|
||||||
@ -22,114 +23,104 @@ public class AuthenticationService : IAuthenticationService
|
|||||||
private readonly Jwt _jwt;
|
private readonly Jwt _jwt;
|
||||||
|
|
||||||
private readonly UserManager<User> _userManager;
|
private readonly UserManager<User> _userManager;
|
||||||
private readonly RoleManager<IdentityRole> _roleManager;
|
|
||||||
private readonly IHttpContextAccessor _contextAccessor;
|
|
||||||
private readonly LinkGenerator _linkGenerator;
|
|
||||||
private readonly IEmailSenderService _emailSender;
|
private readonly IEmailSenderService _emailSender;
|
||||||
private readonly IConfiguration _configuration;
|
private readonly IConfiguration _configuration;
|
||||||
|
|
||||||
public AuthenticationService(UserManager<User> userManager,
|
public AuthenticationService(UserManager<User> userManager, IOptions<Jwt> jwt,
|
||||||
RoleManager<IdentityRole> roleManager, IOptions<Jwt> jwt,
|
|
||||||
IHttpContextAccessor contextAccessor, LinkGenerator linkGenerator,
|
|
||||||
IEmailSenderService emailSender, IConfiguration configuration)
|
IEmailSenderService emailSender, IConfiguration configuration)
|
||||||
{
|
{
|
||||||
_jwt = jwt.Value;
|
_jwt = jwt.Value;
|
||||||
|
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
_roleManager = roleManager;
|
|
||||||
_contextAccessor = contextAccessor;
|
|
||||||
_linkGenerator = linkGenerator;
|
|
||||||
_emailSender = emailSender;
|
_emailSender = emailSender;
|
||||||
_configuration = configuration;
|
_configuration = configuration;
|
||||||
|
|
||||||
_userManager.UserValidators.Clear();
|
_userManager.UserValidators.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<(bool succeeded, string message)> RegisterAsync(RegistrationRequest regRequest)
|
public async Task<(bool succeeded, IActionResult actionResult)> Register(RegistrationRequest request)
|
||||||
{
|
{
|
||||||
var userWithSameEmail = await _userManager.FindByEmailAsync(regRequest.Email);
|
var userWithSameEmail = await _userManager.FindByEmailAsync(request.Email);
|
||||||
if (userWithSameEmail != null)
|
if (userWithSameEmail != null)
|
||||||
{
|
{
|
||||||
return (false, "Email is already registered.");
|
return (false, new BadRequestObjectResult("Email is already registered."));
|
||||||
}
|
}
|
||||||
|
|
||||||
var userWithSamePhone = await _userManager.Users
|
var userWithSamePhone = await _userManager.Users
|
||||||
.SingleOrDefaultAsync(u => u.PhoneNumber == regRequest.PhoneNumber);
|
.SingleOrDefaultAsync(u => u.PhoneNumber == request.PhoneNumber);
|
||||||
if (userWithSamePhone != null)
|
if (userWithSamePhone != null)
|
||||||
{
|
{
|
||||||
return (false, "Phone is already registered.");
|
return (false, new BadRequestObjectResult("Phone is already registered."));
|
||||||
}
|
}
|
||||||
|
|
||||||
var user = new User
|
var user = new User
|
||||||
{
|
{
|
||||||
UserName = "temp",
|
UserName = "temp",
|
||||||
FirstName = regRequest.FirstName,
|
FirstName = request.FirstName,
|
||||||
LastName = regRequest.LastName,
|
LastName = request.LastName,
|
||||||
Patronymic = regRequest.Patronymic,
|
Patronymic = request.Patronymic,
|
||||||
Email = regRequest.Email,
|
Email = request.Email,
|
||||||
PhoneNumber = regRequest.PhoneNumber
|
PhoneNumber = request.PhoneNumber
|
||||||
};
|
};
|
||||||
|
|
||||||
var createUserResult = await _userManager.CreateAsync(user, regRequest.Password);
|
var createUserResult = await _userManager.CreateAsync(user, request.Password);
|
||||||
if (!createUserResult.Succeeded)
|
if (!createUserResult.Succeeded)
|
||||||
{
|
{
|
||||||
return (false, $"{createUserResult.Errors?.First().Description}");
|
return (false, new BadRequestObjectResult(createUserResult.Errors));
|
||||||
}
|
}
|
||||||
|
|
||||||
await _userManager.AddToRoleAsync(user, Identity.DefaultRole.ToString());
|
await _userManager.AddToRoleAsync(user, Identity.DefaultRole.ToString());
|
||||||
|
|
||||||
var token = await _userManager.GenerateEmailConfirmationTokenAsync(user);
|
var emailConfirmationToken = await _userManager.GenerateEmailConfirmationTokenAsync(user);
|
||||||
var confirmationLink = _linkGenerator.GetUriByAction(_contextAccessor.HttpContext,
|
var confirmationMessage =
|
||||||
"confirmEmail", "authentication",
|
"Someone registered an account on our service with your email.\n" +
|
||||||
new { email = user.Email, token = token, redirectionUrl = regRequest.EmailConfirmationRedirectUrl },
|
$"Here is your confirmation code: {emailConfirmationToken}\n\n" +
|
||||||
_contextAccessor.HttpContext.Request.Scheme);
|
"If this was not you, please ignore this message.";
|
||||||
|
|
||||||
|
try { await _emailSender.SendMail(user.Email, "Email confirmation", confirmationMessage); }
|
||||||
|
catch (Exception e) { /* ignored */ }
|
||||||
|
|
||||||
|
// TODO: Add phone number confirmation
|
||||||
|
|
||||||
try
|
return (true, null!);
|
||||||
{
|
|
||||||
await _emailSender.SendMail(user.Email, "Email confirmation", confirmationLink);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (true, $"User registered with email {user.Email}. Before signing in confirm your email" +
|
|
||||||
$"by following a link sent to registered email address.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<(bool succeeded, string? message)> ConfirmEmailAsync(string email, string token)
|
public async Task<(bool succeeded, IActionResult actionResult)> ConfirmRegistrationEmail(ConfirmRegistrationEmailRequest request)
|
||||||
{
|
{
|
||||||
var user = await _userManager.FindByEmailAsync(email);
|
var dbUser = await _userManager.FindByEmailAsync(request.Email);
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
return (false, $"Email {email} not registered");
|
|
||||||
}
|
|
||||||
|
|
||||||
var result = await _userManager.ConfirmEmailAsync(user, token);
|
var result = await _userManager.ConfirmEmailAsync(dbUser, request.Token);
|
||||||
if (!result.Succeeded)
|
if (!result.Succeeded)
|
||||||
{
|
{
|
||||||
return (false, $"Error confirming email {email} with token {token}");
|
return (false, new BadRequestObjectResult($"Error confirming email."));
|
||||||
}
|
}
|
||||||
|
|
||||||
return (true, $"Email {email} confirmed");
|
return (true, null!);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<(bool succeeded, IActionResult actionResult)> ConfirmRegistrationPhoneNumber(ConfirmRegistrationPhoneNumberRequest numberRequest)
|
||||||
|
{
|
||||||
|
var dbUser = await _userManager.Users.FirstAsync(u => u.PhoneNumber == numberRequest.PhoneNumber);
|
||||||
|
|
||||||
|
// TODO: Add phone number confirmation token validation
|
||||||
|
|
||||||
|
return (true, null!);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<(bool succeeded, AuthenticationResponse authResponse, string? refreshToken)>
|
public async Task<(bool succeeded, AuthenticationResponse authResponse, string? refreshToken)>
|
||||||
AuthenticateAsync(AuthenticationRequest authRequest)
|
AuthenticateAsync(AuthenticationRequest request)
|
||||||
{
|
{
|
||||||
var authResponse = new AuthenticationResponse();
|
var authResponse = new AuthenticationResponse();
|
||||||
|
|
||||||
User user;
|
var user = await _userManager.FindByEmailAsync(request.Email);
|
||||||
|
|
||||||
user = await _userManager.FindByEmailAsync(authRequest.Email);
|
|
||||||
|
|
||||||
if (user == null)
|
if (user == null)
|
||||||
{
|
{
|
||||||
authResponse.Message = $"No accounts registered with {authRequest.Email}.";
|
authResponse.Message = $"No accounts registered with {request.Email}.";
|
||||||
return (false, authResponse, null);
|
return (false, authResponse, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!await _userManager.CheckPasswordAsync(user, authRequest.Password))
|
if (!await _userManager.CheckPasswordAsync(user, request.Password))
|
||||||
{
|
{
|
||||||
authResponse.Message = $"Incorrect email or password.";
|
authResponse.Message = $"Incorrect email or password.";
|
||||||
return (false, authResponse, null);
|
return (false, authResponse, null);
|
||||||
@ -160,13 +151,13 @@ public class AuthenticationService : IAuthenticationService
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async Task<(bool succeeded, AuthenticationResponse authResponse, string? refreshToken)>
|
public async Task<(bool succeeded, AuthenticationResponse authResponse, string? refreshToken)>
|
||||||
AuthenticateWithGoogleAsync(GoogleAuthenticationRequest authRequest)
|
AuthenticateWithGoogleAsync(GoogleAuthenticationRequest request)
|
||||||
{
|
{
|
||||||
GoogleJsonWebSignature.ValidationSettings settings = new GoogleJsonWebSignature.ValidationSettings();
|
GoogleJsonWebSignature.ValidationSettings settings = new GoogleJsonWebSignature.ValidationSettings();
|
||||||
|
|
||||||
settings.Audience = new List<string> { _configuration["Authentication:Google:ClientId"] };
|
settings.Audience = new List<string> { _configuration["Authentication:Google:ClientId"] };
|
||||||
|
|
||||||
GoogleJsonWebSignature.Payload payload = GoogleJsonWebSignature.ValidateAsync(authRequest.IdToken, settings).Result;
|
GoogleJsonWebSignature.Payload payload = GoogleJsonWebSignature.ValidateAsync(request.IdToken, settings).Result;
|
||||||
|
|
||||||
var authResponse = new AuthenticationResponse();
|
var authResponse = new AuthenticationResponse();
|
||||||
|
|
||||||
@ -209,8 +200,8 @@ public class AuthenticationService : IAuthenticationService
|
|||||||
return (true, authResponse, refreshTokenString);
|
return (true, authResponse, refreshTokenString);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<(bool succeeded, AuthenticationResponse authResponse,
|
public async Task<(bool succeeded, AuthenticationResponse authResponse, string? refreshToken)>
|
||||||
string? refreshToken)> RenewRefreshTokenAsync(string? token)
|
RenewRefreshTokenAsync(string? token)
|
||||||
{
|
{
|
||||||
var authResponse = new AuthenticationResponse();
|
var authResponse = new AuthenticationResponse();
|
||||||
|
|
||||||
|
@ -22,6 +22,11 @@ public class EmailSenderService : IEmailSenderService
|
|||||||
_smtpClient = new SmtpClient();
|
_smtpClient = new SmtpClient();
|
||||||
_smtpClient.SslProtocols = SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Tls13;
|
_smtpClient.SslProtocols = SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Tls13;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~EmailSenderService()
|
||||||
|
{
|
||||||
|
_smtpClient.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<(bool succeeded, string message)> SendMail(string toEmail, string subject, string message)
|
public async Task<(bool succeeded, string message)> SendMail(string toEmail, string subject, string message)
|
||||||
{
|
{
|
||||||
@ -38,7 +43,6 @@ public class EmailSenderService : IEmailSenderService
|
|||||||
await _smtpClient.AuthenticateAsync(Encoding.ASCII, _smtpCredentials.User, _smtpCredentials.Password);
|
await _smtpClient.AuthenticateAsync(Encoding.ASCII, _smtpCredentials.User, _smtpCredentials.Password);
|
||||||
await _smtpClient.SendAsync(mailMessage);
|
await _smtpClient.SendAsync(mailMessage);
|
||||||
await _smtpClient.DisconnectAsync(true);
|
await _smtpClient.DisconnectAsync(true);
|
||||||
_smtpClient.Dispose();
|
|
||||||
|
|
||||||
return (true, "Letter has been sent successfully");
|
return (true, "Letter has been sent successfully");
|
||||||
}
|
}
|
||||||
|
19
Server/Services/IAccountManagementService.cs
Normal file
19
Server/Services/IAccountManagementService.cs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using SharedModels.Requests;
|
||||||
|
|
||||||
|
namespace Server.Services;
|
||||||
|
|
||||||
|
public interface IAccountManagementService
|
||||||
|
{
|
||||||
|
Task<(bool isSucceed, IActionResult actionResult)> ChangeInformation(ChangeInformationRequest request);
|
||||||
|
|
||||||
|
Task<(bool isSucceed, IActionResult actionResult)> ChangeEmail(ChangeEmailRequest request);
|
||||||
|
|
||||||
|
Task<(bool isSucceed, IActionResult actionResult)> ConfirmChangeEmail(ConfirmChangeEmailRequest request);
|
||||||
|
|
||||||
|
Task<(bool isSucceed, IActionResult actionResult)> ChangePhoneNumber(ChangePhoneNumberRequest request);
|
||||||
|
|
||||||
|
Task<(bool isSucceed, IActionResult actionResult)> ConfirmPhoneNumberChange(ConfirmChangePhoneNumberRequest request);
|
||||||
|
|
||||||
|
Task<(bool isSucceed, IActionResult actionResult)> ChangePassword(ChangePasswordRequest request);
|
||||||
|
}
|
@ -1,3 +1,4 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using SharedModels.Requests;
|
using SharedModels.Requests;
|
||||||
using SharedModels.Responses;
|
using SharedModels.Responses;
|
||||||
|
|
||||||
@ -5,15 +6,17 @@ namespace Server.Services;
|
|||||||
|
|
||||||
public interface IAuthenticationService
|
public interface IAuthenticationService
|
||||||
{
|
{
|
||||||
Task<(bool succeeded, string message)> RegisterAsync(RegistrationRequest regRequest);
|
Task<(bool succeeded, IActionResult actionResult)> Register(RegistrationRequest request);
|
||||||
|
|
||||||
|
Task<(bool succeeded, IActionResult actionResult)> ConfirmRegistrationEmail(ConfirmRegistrationEmailRequest request);
|
||||||
|
|
||||||
|
Task<(bool succeeded, IActionResult actionResult)> ConfirmRegistrationPhoneNumber(ConfirmRegistrationPhoneNumberRequest numberRequest);
|
||||||
|
|
||||||
Task<(bool succeeded, string message)> ConfirmEmailAsync(string email, string token);
|
Task<(bool succeeded, AuthenticationResponse authResponse, string? refreshToken)>
|
||||||
|
AuthenticateAsync(AuthenticationRequest request);
|
||||||
|
|
||||||
Task<(bool succeeded, AuthenticationResponse authResponse, string? refreshToken)>
|
Task<(bool succeeded, AuthenticationResponse authResponse, string? refreshToken)>
|
||||||
AuthenticateAsync(AuthenticationRequest authRequest);
|
AuthenticateWithGoogleAsync(GoogleAuthenticationRequest request);
|
||||||
|
|
||||||
Task<(bool succeeded, AuthenticationResponse authResponse, string? refreshToken)>
|
|
||||||
AuthenticateWithGoogleAsync(GoogleAuthenticationRequest authRequest);
|
|
||||||
|
|
||||||
Task<(bool succeeded, AuthenticationResponse authResponse, string? refreshToken)>
|
Task<(bool succeeded, AuthenticationResponse authResponse, string? refreshToken)>
|
||||||
RenewRefreshTokenAsync(string? token);
|
RenewRefreshTokenAsync(string? token);
|
||||||
|
@ -10,6 +10,5 @@ public interface ISessionUserService
|
|||||||
public Task<bool> IsAuthUserCompanyVehicleEnrollment(int enrollmentId);
|
public Task<bool> IsAuthUserCompanyVehicleEnrollment(int enrollmentId);
|
||||||
public Task<bool> IsAuthUserCompanyDriver(string driverId);
|
public Task<bool> IsAuthUserCompanyDriver(string driverId);
|
||||||
|
|
||||||
|
|
||||||
public Task<bool> IsAuthUserReview(int reviewId);
|
public Task<bool> IsAuthUserReview(int reviewId);
|
||||||
}
|
}
|
@ -8,14 +8,15 @@ namespace Server.Services;
|
|||||||
|
|
||||||
public interface IUserManagementService
|
public interface IUserManagementService
|
||||||
{
|
{
|
||||||
Task<(bool isSucceeded, IActionResult? actionResult, UserDto user)> AddUser(CreateUserDto createUserDto);
|
Task<(bool isSucceeded, IActionResult actionResult, UserDto user)> AddUser(CreateUserDto createUserDto);
|
||||||
|
|
||||||
Task<(bool isSucceeded, IActionResult? actionResult, IEnumerable<ExpandoObject> users, PagingMetadata<ExpandoObject> pagingMetadata)>
|
Task<(bool isSucceeded, IActionResult actionResult, IEnumerable<ExpandoObject> users, PagingMetadata<ExpandoObject> pagingMetadata)>
|
||||||
GetUsers(UserParameters parameters);
|
GetUsers(UserParameters parameters);
|
||||||
|
|
||||||
|
Task<(bool isSucceeded, IActionResult actionResult, ExpandoObject user)> GetUser(string id, string? fields);
|
||||||
|
|
||||||
|
Task<(bool isSucceeded, IActionResult actionResult, UserDto user)>
|
||||||
|
UpdateUser(string id, UpdateUserDto updateUserDto);
|
||||||
|
|
||||||
Task<(bool isSucceeded, IActionResult? actionResult, ExpandoObject user)> GetUser(string id, string? fields);
|
Task<(bool isSucceed, IActionResult actionResult)> DeleteUser(string id);
|
||||||
|
|
||||||
Task<(bool isSucceeded, IActionResult? actionResult, UserDto user)> UpdateUser(string id, UpdateUserDto updateUserDto);
|
|
||||||
|
|
||||||
Task<(bool isSucceed, IActionResult? actionResult)> DeleteUser(string id);
|
|
||||||
}
|
}
|
@ -9,6 +9,7 @@ using Server.Models;
|
|||||||
using SharedModels.DataTransferObjects.Model;
|
using SharedModels.DataTransferObjects.Model;
|
||||||
using SharedModels.QueryParameters;
|
using SharedModels.QueryParameters;
|
||||||
using SharedModels.QueryParameters.Objects;
|
using SharedModels.QueryParameters.Objects;
|
||||||
|
using SharedModels.Requests;
|
||||||
|
|
||||||
namespace Server.Services;
|
namespace Server.Services;
|
||||||
|
|
||||||
@ -21,9 +22,9 @@ public class UserManagementService : IUserManagementService
|
|||||||
private readonly IDataShaper<UserDto> _userDataShaper;
|
private readonly IDataShaper<UserDto> _userDataShaper;
|
||||||
private readonly IPager<ExpandoObject> _pager;
|
private readonly IPager<ExpandoObject> _pager;
|
||||||
|
|
||||||
public UserManagementService(IMapper mapper, UserManager<User> userManager, RoleManager<IdentityRole> roleManager,
|
public UserManagementService(IMapper mapper, UserManager<User> userManager,
|
||||||
ISortHelper<ExpandoObject> userSortHelper, IDataShaper<UserDto> userDataShaper, IPager<ExpandoObject> pager,
|
RoleManager<IdentityRole> roleManager, ISortHelper<ExpandoObject> userSortHelper,
|
||||||
ApplicationDbContext dbContext)
|
IDataShaper<UserDto> userDataShaper, IPager<ExpandoObject> pager)
|
||||||
{
|
{
|
||||||
_mapper = mapper;
|
_mapper = mapper;
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
@ -35,7 +36,8 @@ public class UserManagementService : IUserManagementService
|
|||||||
_userManager.UserValidators.Clear();
|
_userManager.UserValidators.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<(bool isSucceeded, IActionResult? actionResult, UserDto user)> AddUser(CreateUserDto createUserDto)
|
public async Task<(bool isSucceeded, IActionResult actionResult, UserDto user)>
|
||||||
|
AddUser(CreateUserDto createUserDto)
|
||||||
{
|
{
|
||||||
var user = _mapper.Map<User>(createUserDto);
|
var user = _mapper.Map<User>(createUserDto);
|
||||||
user.BirthDate = user.BirthDate == null ? null : new DateTime(user.BirthDate.Value.Ticks, DateTimeKind.Utc);
|
user.BirthDate = user.BirthDate == null ? null : new DateTime(user.BirthDate.Value.Ticks, DateTimeKind.Utc);
|
||||||
@ -45,12 +47,12 @@ public class UserManagementService : IUserManagementService
|
|||||||
|
|
||||||
if (await _userManager.FindByEmailAsync(user.Email) != null)
|
if (await _userManager.FindByEmailAsync(user.Email) != null)
|
||||||
{
|
{
|
||||||
return (false, new BadRequestObjectResult("Email already registered"), null);
|
return (false, new BadRequestObjectResult("Email already registered"), null!);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user.PhoneNumber != null && await _userManager.Users.FirstOrDefaultAsync(u => u.PhoneNumber == user.PhoneNumber) != null)
|
if (user.PhoneNumber != null && await _userManager.Users.FirstOrDefaultAsync(u => u.PhoneNumber == user.PhoneNumber) != null)
|
||||||
{
|
{
|
||||||
return (false, new BadRequestObjectResult("Phone number already registered"), null);
|
return (false, new BadRequestObjectResult("Phone number already registered"), null!);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (createUserDto.Roles != null!)
|
if (createUserDto.Roles != null!)
|
||||||
@ -59,7 +61,7 @@ public class UserManagementService : IUserManagementService
|
|||||||
{
|
{
|
||||||
if (!await _roleManager.RoleExistsAsync(role))
|
if (!await _roleManager.RoleExistsAsync(role))
|
||||||
{
|
{
|
||||||
return (false, new BadRequestObjectResult($"Roles \"{role}\" doesn't exist"), null);
|
return (false, new BadRequestObjectResult($"Roles \"{role}\" doesn't exist"), null!);
|
||||||
}
|
}
|
||||||
|
|
||||||
userDto.Roles.Add(role);
|
userDto.Roles.Add(role);
|
||||||
@ -71,11 +73,11 @@ public class UserManagementService : IUserManagementService
|
|||||||
|
|
||||||
userDto.Id = user.Id;
|
userDto.Id = user.Id;
|
||||||
|
|
||||||
return (true, null, userDto);
|
return (true, null!, userDto);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<(bool isSucceeded, IActionResult? actionResult, IEnumerable<ExpandoObject> users,
|
public async Task<(bool isSucceeded, IActionResult actionResult, IEnumerable<ExpandoObject> users, PagingMetadata<ExpandoObject> pagingMetadata)>
|
||||||
PagingMetadata<ExpandoObject> pagingMetadata)> GetUsers(UserParameters parameters)
|
GetUsers(UserParameters parameters)
|
||||||
{
|
{
|
||||||
var dbUsers = _userManager.Users.Include(u => u.Company)
|
var dbUsers = _userManager.Users.Include(u => u.Company)
|
||||||
.Include(u => u.Reviews).Include(u => u.TicketGroups)
|
.Include(u => u.Reviews).Include(u => u.TicketGroups)
|
||||||
@ -108,7 +110,7 @@ public class UserManagementService : IUserManagementService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (true, null, shapedData, pagingMetadata);
|
return (true, null!, shapedData, pagingMetadata);
|
||||||
|
|
||||||
void SearchByAllUserFields(ref IQueryable<User> users, string? search)
|
void SearchByAllUserFields(ref IQueryable<User> users, string? search)
|
||||||
{
|
{
|
||||||
@ -126,7 +128,7 @@ public class UserManagementService : IUserManagementService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<(bool isSucceeded, IActionResult? actionResult, ExpandoObject user)>
|
public async Task<(bool isSucceeded, IActionResult actionResult, ExpandoObject user)>
|
||||||
GetUser(string id, string? fields)
|
GetUser(string id, string? fields)
|
||||||
{
|
{
|
||||||
var dbUser = await _userManager.Users.Include(u => u.Employer).
|
var dbUser = await _userManager.Users.Include(u => u.Employer).
|
||||||
@ -142,24 +144,24 @@ public class UserManagementService : IUserManagementService
|
|||||||
fields = UserParameters.DefaultFields;
|
fields = UserParameters.DefaultFields;
|
||||||
}
|
}
|
||||||
|
|
||||||
var userDto = _mapper.Map<DriverDto>(dbUser);
|
var userDto = _mapper.Map<UserDto>(dbUser);
|
||||||
var shapedData = _userDataShaper.ShapeData(userDto, fields);
|
var shapedData = _userDataShaper.ShapeData(userDto, fields);
|
||||||
|
|
||||||
return (true, null, shapedData);
|
return (true, null!, shapedData);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<(bool isSucceeded, IActionResult? actionResult, UserDto user)>
|
public async Task<(bool isSucceeded, IActionResult actionResult, UserDto user)>
|
||||||
UpdateUser(string id, UpdateUserDto updateUserDto)
|
UpdateUser(string id, UpdateUserDto updateUserDto)
|
||||||
{
|
{
|
||||||
if (id != updateUserDto.Id)
|
if (id != updateUserDto.Id)
|
||||||
{
|
{
|
||||||
return (false, new BadRequestObjectResult("Object and query ids don't match"), null);
|
return (false, new BadRequestObjectResult("Object and query ids don't match"), null!);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!await _userManager.Users.AnyAsync(u => u.Id == id))
|
if (!await _userManager.Users.AnyAsync(u => u.Id == id))
|
||||||
{
|
{
|
||||||
|
|
||||||
return (false, new NotFoundResult(), null);
|
return (false, new NotFoundResult(), null!);
|
||||||
}
|
}
|
||||||
|
|
||||||
var dbUser = await _userManager.FindByIdAsync(id);
|
var dbUser = await _userManager.FindByIdAsync(id);
|
||||||
@ -198,7 +200,7 @@ public class UserManagementService : IUserManagementService
|
|||||||
{
|
{
|
||||||
if (!await _roleManager.RoleExistsAsync(role))
|
if (!await _roleManager.RoleExistsAsync(role))
|
||||||
{
|
{
|
||||||
return (false, new BadRequestObjectResult($"Roles \"{role}\" doesn't exist"), null);
|
return (false, new BadRequestObjectResult($"Roles \"{role}\" doesn't exist"), null!);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,10 +214,10 @@ public class UserManagementService : IUserManagementService
|
|||||||
|
|
||||||
await _userManager.UpdateAsync(dbUser);
|
await _userManager.UpdateAsync(dbUser);
|
||||||
|
|
||||||
return (true, null, userDto);
|
return (true, null!, userDto);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<(bool isSucceed, IActionResult? actionResult)> DeleteUser(string id)
|
public async Task<(bool isSucceed, IActionResult actionResult)> DeleteUser(string id)
|
||||||
{
|
{
|
||||||
var dbUser = await _userManager.FindByIdAsync(id);
|
var dbUser = await _userManager.FindByIdAsync(id);
|
||||||
|
|
||||||
@ -226,6 +228,6 @@ public class UserManagementService : IUserManagementService
|
|||||||
|
|
||||||
await _userManager.DeleteAsync(dbUser);
|
await _userManager.DeleteAsync(dbUser);
|
||||||
|
|
||||||
return (true, null);
|
return (true, null!);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,32 +0,0 @@
|
|||||||
{
|
|
||||||
"Logging": {
|
|
||||||
"LogLevel": {
|
|
||||||
"Default": "Information",
|
|
||||||
"Microsoft.AspNetCore": "Warning"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"AllowedHosts": "*",
|
|
||||||
"ConnectionStrings": {
|
|
||||||
"DefaultConnection": "host=localhost;database=auto.bus;user id=postgres;password=postgres;Include Error Detail = true"
|
|
||||||
},
|
|
||||||
"ApplicationName": "auto.bus",
|
|
||||||
"SmtpCredentials": {
|
|
||||||
"Host": "",
|
|
||||||
"Port": 587,
|
|
||||||
"User": "",
|
|
||||||
"Password": ""
|
|
||||||
},
|
|
||||||
"Authentication": {
|
|
||||||
"Google": {
|
|
||||||
"ClientId": "",
|
|
||||||
"ClientSecret": ""
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Jwt": {
|
|
||||||
"Key": "Secret which will never be exposed",
|
|
||||||
"Audience": "Application URL",
|
|
||||||
"Issuer": "Application URL",
|
|
||||||
"ValidityInMinutes": 60,
|
|
||||||
"RefreshTokenValidityInDays": 10
|
|
||||||
}
|
|
||||||
}
|
|
@ -7,10 +7,10 @@
|
|||||||
},
|
},
|
||||||
"AllowedHosts": "*",
|
"AllowedHosts": "*",
|
||||||
"ConnectionStrings": {
|
"ConnectionStrings": {
|
||||||
"DefaultConnection": "host=localhost;database=auto.bus;user id=postgres;password=postgres;Include Error Detail = true"
|
"DefaultConnection": ""
|
||||||
},
|
},
|
||||||
"UseApiExplorer": true,
|
"UseApiExplorer": false,
|
||||||
"ApplicationName": "auto.bus",
|
"ApplicationName": "",
|
||||||
"SmtpCredentials": {
|
"SmtpCredentials": {
|
||||||
"Host": "",
|
"Host": "",
|
||||||
"Port": 587,
|
"Port": 587,
|
||||||
@ -24,10 +24,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Jwt": {
|
"Jwt": {
|
||||||
"Key": "Secret which will never be exposed",
|
"Key": "",
|
||||||
"Audience": "Application URL",
|
"Audience": "",
|
||||||
"Issuer": "Application URL",
|
"Issuer": "",
|
||||||
"ValidityInMinutes": 1,
|
"ValidityInMinutes": 5,
|
||||||
"RefreshTokenValidityInDays": 10
|
"RefreshTokenValidityInDays": 10
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
10
SharedModels/Requests/ChangeEmailRequest.cs
Normal file
10
SharedModels/Requests/ChangeEmailRequest.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace SharedModels.Requests;
|
||||||
|
|
||||||
|
public class ChangeEmailRequest
|
||||||
|
{
|
||||||
|
[Required]
|
||||||
|
[DataType(DataType.EmailAddress)]
|
||||||
|
public string NewEmail { get; set; } = null!;
|
||||||
|
}
|
21
SharedModels/Requests/ChangeInformationRequest.cs
Normal file
21
SharedModels/Requests/ChangeInformationRequest.cs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using Utils;
|
||||||
|
|
||||||
|
namespace SharedModels.Requests;
|
||||||
|
|
||||||
|
public class ChangeInformationRequest
|
||||||
|
{
|
||||||
|
[Required]
|
||||||
|
public string FistName { get; set; } = null!;
|
||||||
|
[Required]
|
||||||
|
public string LastName { get; set; } = null!;
|
||||||
|
[Required]
|
||||||
|
public string Patronymic { get; set; } = null!;
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
[DataType(DataType.Date)]
|
||||||
|
public DateTime BirthDate { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public Identity.Gender Gender { get; set; }
|
||||||
|
}
|
12
SharedModels/Requests/ChangePasswordRequest.cs
Normal file
12
SharedModels/Requests/ChangePasswordRequest.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace SharedModels.Requests;
|
||||||
|
|
||||||
|
public class ChangePasswordRequest
|
||||||
|
{
|
||||||
|
[Required]
|
||||||
|
public string CurrentPassword { get; set; } = null!;
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string NewPassword { get; set; } = null!;
|
||||||
|
}
|
10
SharedModels/Requests/ChangePhoneNumberRequest.cs
Normal file
10
SharedModels/Requests/ChangePhoneNumberRequest.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace SharedModels.Requests;
|
||||||
|
|
||||||
|
public class ChangePhoneNumberRequest
|
||||||
|
{
|
||||||
|
[Required]
|
||||||
|
[DataType(DataType.PhoneNumber)]
|
||||||
|
public string PhoneNumber { get; set; } = null!;
|
||||||
|
}
|
9
SharedModels/Requests/ConfirmChangeEmailRequest.cs
Normal file
9
SharedModels/Requests/ConfirmChangeEmailRequest.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace SharedModels.Requests;
|
||||||
|
|
||||||
|
public class ConfirmChangeEmailRequest : ChangeEmailRequest
|
||||||
|
{
|
||||||
|
[Required]
|
||||||
|
public string Token { get; set; } = null!;
|
||||||
|
}
|
9
SharedModels/Requests/ConfirmChangePhoneNumberRequest.cs
Normal file
9
SharedModels/Requests/ConfirmChangePhoneNumberRequest.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace SharedModels.Requests;
|
||||||
|
|
||||||
|
public class ConfirmChangePhoneNumberRequest : ChangePhoneNumberRequest
|
||||||
|
{
|
||||||
|
[Required]
|
||||||
|
public string Token { get; set; } = null!;
|
||||||
|
}
|
13
SharedModels/Requests/ConfirmRegistrationEmailRequest.cs
Normal file
13
SharedModels/Requests/ConfirmRegistrationEmailRequest.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace SharedModels.Requests;
|
||||||
|
|
||||||
|
public class ConfirmRegistrationEmailRequest
|
||||||
|
{
|
||||||
|
[Required]
|
||||||
|
[DataType(DataType.EmailAddress)]
|
||||||
|
public string Email { get; set; } = null!;
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string Token { get; set; } = null!;
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace SharedModels.Requests;
|
||||||
|
|
||||||
|
public class ConfirmRegistrationPhoneNumberRequest
|
||||||
|
{
|
||||||
|
[Required]
|
||||||
|
[DataType(DataType.PhoneNumber)]
|
||||||
|
public string PhoneNumber { get; set; } = null!;
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string Token { get; set; } = null!;
|
||||||
|
}
|
@ -24,7 +24,4 @@ public class RegistrationRequest
|
|||||||
[Required(ErrorMessage = "Password is required")]
|
[Required(ErrorMessage = "Password is required")]
|
||||||
[DataType(DataType.Password)]
|
[DataType(DataType.Password)]
|
||||||
public string Password { get; set; } = null!;
|
public string Password { get; set; } = null!;
|
||||||
|
|
||||||
[Url]
|
|
||||||
public string EmailConfirmationRedirectUrl { get; set; } = null!;
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user