file-scoped namespaces
This commit is contained in:
@@ -1,4 +1,3 @@
|
|||||||
namespace ApplicationLayer.GeneralExceptions
|
namespace ApplicationLayer.GeneralExceptions;
|
||||||
{
|
|
||||||
public class AlreadyExistsException(string message) : ApiException(message);
|
public class AlreadyExistsException(string message) : ApiException(message);
|
||||||
}
|
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
namespace ApplicationLayer.GeneralExceptions
|
namespace ApplicationLayer.GeneralExceptions;
|
||||||
{
|
|
||||||
public class ApiException(string message) : Exception(message);
|
public class ApiException(string message) : Exception(message);
|
||||||
}
|
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
namespace ApplicationLayer.InfrastructureServicesInterfaces
|
namespace ApplicationLayer.InfrastructureServicesInterfaces;
|
||||||
|
|
||||||
|
public interface IDateTimeProvider
|
||||||
{
|
{
|
||||||
public interface IDateTimeProvider
|
/// Returns current date and time
|
||||||
{
|
DateTime Now();
|
||||||
/// Returns current date and time
|
}
|
||||||
DateTime Now();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
namespace ApplicationLayer.InfrastructureServicesInterfaces
|
namespace ApplicationLayer.InfrastructureServicesInterfaces;
|
||||||
|
|
||||||
|
public interface IUserIdProvider
|
||||||
{
|
{
|
||||||
public interface IUserIdProvider
|
/// Returns identifier of authenticated user who sent the request
|
||||||
{
|
Guid GetUserId();
|
||||||
/// Returns identifier of authenticated user who sent the request
|
}
|
||||||
Guid GetUserId();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,50 +1,49 @@
|
|||||||
using Domains.ApplicantDomain;
|
using Domains.ApplicantDomain;
|
||||||
|
|
||||||
namespace ApplicationLayer.Services.Applicants.Models
|
namespace ApplicationLayer.Services.Applicants.Models;
|
||||||
|
|
||||||
|
/// Model of <see cref="Applicant"/>
|
||||||
|
public class ApplicantModel
|
||||||
{
|
{
|
||||||
/// Model of <see cref="Applicant"/>
|
/// <inheritdoc cref="Applicant.Name"/>
|
||||||
public class ApplicantModel
|
public Name Name { get; set; } = null!;
|
||||||
{
|
|
||||||
/// <inheritdoc cref="Applicant.Name"/>
|
|
||||||
public Name Name { get; set; } = null!;
|
|
||||||
|
|
||||||
/// <inheritdoc cref="Applicant.Passport"/>
|
/// <inheritdoc cref="Applicant.Passport"/>
|
||||||
public Passport Passport { get; set; } = null!;
|
public Passport Passport { get; set; } = null!;
|
||||||
|
|
||||||
/// <inheritdoc cref="Applicant.BirthDate"/>
|
/// <inheritdoc cref="Applicant.BirthDate"/>
|
||||||
public DateTime BirthDate { get; set; }
|
public DateTime BirthDate { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc cref="Applicant.CountryOfBirth"/>
|
/// <inheritdoc cref="Applicant.CountryOfBirth"/>
|
||||||
public string CountryOfBirth { get; set; } = null!;
|
public string CountryOfBirth { get; set; } = null!;
|
||||||
|
|
||||||
/// <inheritdoc cref="Applicant.CityOfBirth"/>
|
/// <inheritdoc cref="Applicant.CityOfBirth"/>
|
||||||
public string CityOfBirth { get; set; } = null!;
|
public string CityOfBirth { get; set; } = null!;
|
||||||
|
|
||||||
/// <inheritdoc cref="Applicant.Citizenship"/>
|
/// <inheritdoc cref="Applicant.Citizenship"/>
|
||||||
public string Citizenship { get; set; } = null!;
|
public string Citizenship { get; set; } = null!;
|
||||||
|
|
||||||
/// <inheritdoc cref="Applicant.CitizenshipByBirth"/>
|
/// <inheritdoc cref="Applicant.CitizenshipByBirth"/>
|
||||||
public string CitizenshipByBirth { get; set; } = null!;
|
public string CitizenshipByBirth { get; set; } = null!;
|
||||||
|
|
||||||
/// <inheritdoc cref="Applicant.Gender"/>
|
/// <inheritdoc cref="Applicant.Gender"/>
|
||||||
public Gender Gender { get; set; }
|
public Gender Gender { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc cref="Applicant.MaritalStatus"/>
|
/// <inheritdoc cref="Applicant.MaritalStatus"/>
|
||||||
public MaritalStatus MaritalStatus { get; set; }
|
public MaritalStatus MaritalStatus { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc cref="Applicant.FatherName"/>
|
/// <inheritdoc cref="Applicant.FatherName"/>
|
||||||
public Name FatherName { get; set; } = null!;
|
public Name FatherName { get; set; } = null!;
|
||||||
|
|
||||||
/// <inheritdoc cref="Applicant.MotherName"/>
|
/// <inheritdoc cref="Applicant.MotherName"/>
|
||||||
public Name MotherName { get; set; } = null!;
|
public Name MotherName { get; set; } = null!;
|
||||||
|
|
||||||
/// <inheritdoc cref="Applicant.JobTitle"/>
|
/// <inheritdoc cref="Applicant.JobTitle"/>
|
||||||
public string JobTitle { get; set; } = null!;
|
public string JobTitle { get; set; } = null!;
|
||||||
|
|
||||||
/// <inheritdoc cref="Applicant.PlaceOfWork"/>
|
/// <inheritdoc cref="Applicant.PlaceOfWork"/>
|
||||||
public PlaceOfWork PlaceOfWork { get; set; } = null!;
|
public PlaceOfWork PlaceOfWork { get; set; } = null!;
|
||||||
|
|
||||||
/// <inheritdoc cref="Applicant.IsNonResident"/>
|
/// <inheritdoc cref="Applicant.IsNonResident"/>
|
||||||
public bool IsNonResident { get; set; }
|
public bool IsNonResident { get; set; }
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@@ -1,16 +1,15 @@
|
|||||||
using Domains.ApplicantDomain;
|
using Domains.ApplicantDomain;
|
||||||
|
|
||||||
namespace ApplicationLayer.Services.Applicants.Models
|
namespace ApplicationLayer.Services.Applicants.Models;
|
||||||
|
|
||||||
|
public class PlaceOfWorkModel
|
||||||
{
|
{
|
||||||
public class PlaceOfWorkModel
|
/// Name of hirer
|
||||||
{
|
public string Name { get; set; } = null!;
|
||||||
/// Name of hirer
|
|
||||||
public string Name { get; set; } = null!;
|
|
||||||
|
|
||||||
/// Address of hirer
|
/// Address of hirer
|
||||||
public Address Address { get; set; } = null!;
|
public Address Address { get; set; } = null!;
|
||||||
|
|
||||||
/// Phone number of hirer
|
/// Phone number of hirer
|
||||||
public string PhoneNum { get; set; } = null!;
|
public string PhoneNum { get; set; } = null!;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
namespace ApplicationLayer.Services.AuthServices.Common
|
namespace ApplicationLayer.Services.AuthServices.Common;
|
||||||
{
|
|
||||||
public record AuthData(string Email, string Password);
|
public record AuthData(string Email, string Password);
|
||||||
}
|
|
||||||
@@ -2,12 +2,12 @@
|
|||||||
using ApplicationLayer.Services.AuthServices.NeededServices;
|
using ApplicationLayer.Services.AuthServices.NeededServices;
|
||||||
using Domains.Users;
|
using Domains.Users;
|
||||||
|
|
||||||
namespace ApplicationLayer.Services.AuthServices.LoginService
|
namespace ApplicationLayer.Services.AuthServices.LoginService;
|
||||||
|
|
||||||
|
public class DevelopmentLoginService(IUsersRepository users, ITokenGenerator tokenGenerator) : ILoginService
|
||||||
{
|
{
|
||||||
public class DevelopmentLoginService(IUsersRepository users, ITokenGenerator tokenGenerator) : ILoginService
|
async Task<string> ILoginService.LoginAsync(string email, string password, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
async Task<string> ILoginService.LoginAsync(string email, string password, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
if (email == "admin@mail.ru" && password == "admin")
|
if (email == "admin@mail.ru" && password == "admin")
|
||||||
{
|
{
|
||||||
var admin = new User { Role = Role.Admin };
|
var admin = new User { Role = Role.Admin };
|
||||||
@@ -23,5 +23,4 @@ namespace ApplicationLayer.Services.AuthServices.LoginService
|
|||||||
|
|
||||||
return tokenGenerator.CreateToken(user);
|
return tokenGenerator.CreateToken(user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
using ApplicationLayer.GeneralExceptions;
|
using ApplicationLayer.GeneralExceptions;
|
||||||
|
|
||||||
namespace ApplicationLayer.Services.AuthServices.LoginService.Exceptions
|
namespace ApplicationLayer.Services.AuthServices.LoginService.Exceptions;
|
||||||
{
|
|
||||||
public class IncorrectLoginDataException() : ApiException("Incorrect email or password");
|
public class IncorrectLoginDataException() : ApiException("Incorrect email or password");
|
||||||
}
|
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
namespace ApplicationLayer.Services.AuthServices.LoginService
|
namespace ApplicationLayer.Services.AuthServices.LoginService;
|
||||||
|
|
||||||
|
/// Handles login requests
|
||||||
|
public interface ILoginService
|
||||||
{
|
{
|
||||||
/// Handles login requests
|
/// Handle login request
|
||||||
public interface ILoginService
|
/// <returns>JWT-token</returns>
|
||||||
{
|
Task<string> LoginAsync(string email, string password, CancellationToken cancellationToken);
|
||||||
/// Handle login request
|
}
|
||||||
/// <returns>JWT-token</returns>
|
|
||||||
Task<string> LoginAsync(string email, string password, CancellationToken cancellationToken);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
using ApplicationLayer.Services.AuthServices.LoginService.Exceptions;
|
using ApplicationLayer.Services.AuthServices.LoginService.Exceptions;
|
||||||
using ApplicationLayer.Services.AuthServices.NeededServices;
|
using ApplicationLayer.Services.AuthServices.NeededServices;
|
||||||
|
|
||||||
namespace ApplicationLayer.Services.AuthServices.LoginService
|
namespace ApplicationLayer.Services.AuthServices.LoginService;
|
||||||
|
|
||||||
|
/// <inheritdoc cref="ILoginService"/>
|
||||||
|
public class LoginService(IUsersRepository users, ITokenGenerator tokenGenerator) : ILoginService
|
||||||
{
|
{
|
||||||
/// <inheritdoc cref="ILoginService"/>
|
async Task<string> ILoginService.LoginAsync(string email, string password, CancellationToken cancellationToken)
|
||||||
public class LoginService(IUsersRepository users, ITokenGenerator tokenGenerator) : ILoginService
|
|
||||||
{
|
{
|
||||||
async Task<string> ILoginService.LoginAsync(string email, string password, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var user = await users.FindByEmailAsync(email, cancellationToken);
|
var user = await users.FindByEmailAsync(email, cancellationToken);
|
||||||
if (user is null || user.Password != password)
|
if (user is null || user.Password != password)
|
||||||
{
|
{
|
||||||
@@ -16,5 +16,4 @@ namespace ApplicationLayer.Services.AuthServices.LoginService
|
|||||||
|
|
||||||
return tokenGenerator.CreateToken(user);
|
return tokenGenerator.CreateToken(user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@@ -1,9 +1,8 @@
|
|||||||
using Domains.Users;
|
using Domains.Users;
|
||||||
|
|
||||||
namespace ApplicationLayer.Services.AuthServices.NeededServices
|
namespace ApplicationLayer.Services.AuthServices.NeededServices;
|
||||||
|
|
||||||
|
public interface ITokenGenerator
|
||||||
{
|
{
|
||||||
public interface ITokenGenerator
|
string CreateToken(User user);
|
||||||
{
|
}
|
||||||
string CreateToken(User user);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,21 +1,20 @@
|
|||||||
using ApplicationLayer.InfrastructureServicesInterfaces;
|
using ApplicationLayer.InfrastructureServicesInterfaces;
|
||||||
using Domains.Users;
|
using Domains.Users;
|
||||||
|
|
||||||
namespace ApplicationLayer.Services.AuthServices.NeededServices
|
namespace ApplicationLayer.Services.AuthServices.NeededServices;
|
||||||
{
|
|
||||||
/// Repository pattern for <see cref="User"/>
|
|
||||||
public interface IUsersRepository : IGenericRepository<User>
|
|
||||||
{
|
|
||||||
/// Find <see cref="User"/> by email
|
|
||||||
/// <param name="email"><see cref="User"/>'s email</param>
|
|
||||||
/// <param name="cancellationToken">Cancellation token</param>
|
|
||||||
/// <returns>User or null if not found</returns>
|
|
||||||
Task<User?> FindByEmailAsync(string email, CancellationToken cancellationToken);
|
|
||||||
|
|
||||||
/// Returns all accounts with specific role
|
/// Repository pattern for <see cref="User"/>
|
||||||
/// <param name="role">role</param>
|
public interface IUsersRepository : IGenericRepository<User>
|
||||||
/// <param name="cancellationToken">cancellation token</param>
|
{
|
||||||
/// <returns>list of accounts</returns>
|
/// Find <see cref="User"/> by email
|
||||||
Task<List<User>> GetAllOfRoleAsync(Role role, CancellationToken cancellationToken);
|
/// <param name="email"><see cref="User"/>'s email</param>
|
||||||
}
|
/// <param name="cancellationToken">Cancellation token</param>
|
||||||
}
|
/// <returns>User or null if not found</returns>
|
||||||
|
Task<User?> FindByEmailAsync(string email, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
/// Returns all accounts with specific role
|
||||||
|
/// <param name="role">role</param>
|
||||||
|
/// <param name="cancellationToken">cancellation token</param>
|
||||||
|
/// <returns>list of accounts</returns>
|
||||||
|
Task<List<User>> GetAllOfRoleAsync(Role role, CancellationToken cancellationToken);
|
||||||
|
}
|
||||||
@@ -1,14 +1,13 @@
|
|||||||
using ApplicationLayer.Services.AuthServices.Requests;
|
using ApplicationLayer.Services.AuthServices.Requests;
|
||||||
|
|
||||||
namespace ApplicationLayer.Services.AuthServices.RegisterService
|
namespace ApplicationLayer.Services.AuthServices.RegisterService;
|
||||||
{
|
|
||||||
/// Handles register request
|
|
||||||
public interface IRegisterService
|
|
||||||
{
|
|
||||||
/// Handle <see cref="RegisterApplicantRequest"/>
|
|
||||||
Task RegisterApplicant(RegisterApplicantRequest request, CancellationToken cancellationToken);
|
|
||||||
|
|
||||||
/// Handles <see cref="RegisterRequest"/> and adds approving authority account
|
/// Handles register request
|
||||||
Task RegisterAuthority(RegisterRequest request, CancellationToken cancellationToken);
|
public interface IRegisterService
|
||||||
}
|
{
|
||||||
}
|
/// Handle <see cref="RegisterApplicantRequest"/>
|
||||||
|
Task RegisterApplicant(RegisterApplicantRequest request, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
/// Handles <see cref="RegisterRequest"/> and adds approving authority account
|
||||||
|
Task RegisterAuthority(RegisterRequest request, CancellationToken cancellationToken);
|
||||||
|
}
|
||||||
@@ -6,37 +6,36 @@ using AutoMapper;
|
|||||||
using Domains.ApplicantDomain;
|
using Domains.ApplicantDomain;
|
||||||
using Domains.Users;
|
using Domains.Users;
|
||||||
|
|
||||||
namespace ApplicationLayer.Services.AuthServices.RegisterService
|
namespace ApplicationLayer.Services.AuthServices.RegisterService;
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IRegisterService"/>
|
||||||
|
public class RegisterService(
|
||||||
|
IUsersRepository users,
|
||||||
|
IApplicantsRepository applicants,
|
||||||
|
IUnitOfWork unitOfWork,
|
||||||
|
IMapper mapper) : IRegisterService
|
||||||
{
|
{
|
||||||
/// <inheritdoc cref="IRegisterService"/>
|
async Task IRegisterService.RegisterApplicant(RegisterApplicantRequest request, CancellationToken cancellationToken)
|
||||||
public class RegisterService(
|
|
||||||
IUsersRepository users,
|
|
||||||
IApplicantsRepository applicants,
|
|
||||||
IUnitOfWork unitOfWork,
|
|
||||||
IMapper mapper) : IRegisterService
|
|
||||||
{
|
{
|
||||||
async Task IRegisterService.RegisterApplicant(RegisterApplicantRequest request, CancellationToken cancellationToken)
|
var user = mapper.Map<User>(request.AuthData);
|
||||||
{
|
user.Role = Role.Applicant;
|
||||||
var user = mapper.Map<User>(request.AuthData);
|
|
||||||
user.Role = Role.Applicant;
|
|
||||||
|
|
||||||
var applicant = mapper.Map<Applicant>(request);
|
var applicant = mapper.Map<Applicant>(request);
|
||||||
applicant.UserId = user.Id;
|
applicant.UserId = user.Id;
|
||||||
|
|
||||||
await users.AddAsync(user, cancellationToken);
|
await users.AddAsync(user, cancellationToken);
|
||||||
await applicants.AddAsync(applicant, cancellationToken);
|
await applicants.AddAsync(applicant, cancellationToken);
|
||||||
|
|
||||||
await unitOfWork.SaveAsync(cancellationToken);
|
await unitOfWork.SaveAsync(cancellationToken);
|
||||||
}
|
|
||||||
|
|
||||||
async Task IRegisterService.RegisterAuthority(RegisterRequest request, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var user = mapper.Map<User>(request.AuthData);
|
|
||||||
user.Role = Role.ApprovingAuthority;
|
|
||||||
|
|
||||||
await users.AddAsync(user, cancellationToken);
|
|
||||||
|
|
||||||
await unitOfWork.SaveAsync(cancellationToken);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
async Task IRegisterService.RegisterAuthority(RegisterRequest request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var user = mapper.Map<User>(request.AuthData);
|
||||||
|
user.Role = Role.ApprovingAuthority;
|
||||||
|
|
||||||
|
await users.AddAsync(user, cancellationToken);
|
||||||
|
|
||||||
|
await unitOfWork.SaveAsync(cancellationToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,22 +2,21 @@
|
|||||||
using ApplicationLayer.Services.AuthServices.Common;
|
using ApplicationLayer.Services.AuthServices.Common;
|
||||||
using Domains.ApplicantDomain;
|
using Domains.ApplicantDomain;
|
||||||
|
|
||||||
namespace ApplicationLayer.Services.AuthServices.Requests
|
namespace ApplicationLayer.Services.AuthServices.Requests;
|
||||||
{
|
|
||||||
public record RegisterApplicantRequest(
|
public record RegisterApplicantRequest(
|
||||||
AuthData AuthData,
|
AuthData AuthData,
|
||||||
Name ApplicantName,
|
Name ApplicantName,
|
||||||
Passport Passport,
|
Passport Passport,
|
||||||
DateTime BirthDate,
|
DateTime BirthDate,
|
||||||
string CityOfBirth,
|
string CityOfBirth,
|
||||||
string CountryOfBirth,
|
string CountryOfBirth,
|
||||||
string Citizenship,
|
string Citizenship,
|
||||||
string CitizenshipByBirth,
|
string CitizenshipByBirth,
|
||||||
Gender Gender,
|
Gender Gender,
|
||||||
MaritalStatus MaritalStatus,
|
MaritalStatus MaritalStatus,
|
||||||
Name FatherName,
|
Name FatherName,
|
||||||
Name MotherName,
|
Name MotherName,
|
||||||
string JobTitle,
|
string JobTitle,
|
||||||
PlaceOfWorkModel PlaceOfWork,
|
PlaceOfWorkModel PlaceOfWork,
|
||||||
bool IsNonResident) : RegisterRequest(AuthData);
|
bool IsNonResident) : RegisterRequest(AuthData);
|
||||||
}
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
using ApplicationLayer.Services.AuthServices.Common;
|
using ApplicationLayer.Services.AuthServices.Common;
|
||||||
|
|
||||||
namespace ApplicationLayer.Services.AuthServices.Requests
|
namespace ApplicationLayer.Services.AuthServices.Requests;
|
||||||
{
|
|
||||||
public record RegisterRequest(AuthData AuthData);
|
public record RegisterRequest(AuthData AuthData);
|
||||||
}
|
|
||||||
@@ -3,12 +3,12 @@ using ApplicationLayer.Services.AuthServices.NeededServices;
|
|||||||
using Domains;
|
using Domains;
|
||||||
using FluentValidation;
|
using FluentValidation;
|
||||||
|
|
||||||
namespace ApplicationLayer.Services.AuthServices.Requests.Validation
|
namespace ApplicationLayer.Services.AuthServices.Requests.Validation;
|
||||||
|
|
||||||
|
public class AuthDataValidator : AbstractValidator<AuthData>
|
||||||
{
|
{
|
||||||
public class AuthDataValidator : AbstractValidator<AuthData>
|
public AuthDataValidator(IUsersRepository users)
|
||||||
{
|
{
|
||||||
public AuthDataValidator(IUsersRepository users)
|
|
||||||
{
|
|
||||||
RuleFor(d => d.Email)
|
RuleFor(d => d.Email)
|
||||||
.NotEmpty()
|
.NotEmpty()
|
||||||
.WithMessage("Email can not be empty")
|
.WithMessage("Email can not be empty")
|
||||||
@@ -28,5 +28,4 @@ namespace ApplicationLayer.Services.AuthServices.Requests.Validation
|
|||||||
.MaximumLength(ConfigurationConstraints.PasswordLength)
|
.MaximumLength(ConfigurationConstraints.PasswordLength)
|
||||||
.WithMessage($"Password length must be less than {ConfigurationConstraints.PasswordLength}");
|
.WithMessage($"Password length must be less than {ConfigurationConstraints.PasswordLength}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@@ -2,12 +2,12 @@
|
|||||||
using Domains.ApplicantDomain;
|
using Domains.ApplicantDomain;
|
||||||
using FluentValidation;
|
using FluentValidation;
|
||||||
|
|
||||||
namespace ApplicationLayer.Services.AuthServices.Requests.Validation
|
namespace ApplicationLayer.Services.AuthServices.Requests.Validation;
|
||||||
|
|
||||||
|
public class NameValidator : AbstractValidator<Name>
|
||||||
{
|
{
|
||||||
public class NameValidator : AbstractValidator<Name>
|
public NameValidator()
|
||||||
{
|
{
|
||||||
public NameValidator()
|
|
||||||
{
|
|
||||||
RuleFor(m => m.FirstName)
|
RuleFor(m => m.FirstName)
|
||||||
.NotEmpty()
|
.NotEmpty()
|
||||||
.WithMessage("First Name can not be empty")
|
.WithMessage("First Name can not be empty")
|
||||||
@@ -24,5 +24,4 @@ namespace ApplicationLayer.Services.AuthServices.Requests.Validation
|
|||||||
.MaximumLength(ConfigurationConstraints.NameLength)
|
.MaximumLength(ConfigurationConstraints.NameLength)
|
||||||
.WithMessage($"Patronymic length must be less than {ConfigurationConstraints.NameLength}");
|
.WithMessage($"Patronymic length must be less than {ConfigurationConstraints.NameLength}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@@ -3,12 +3,12 @@ using Domains;
|
|||||||
using Domains.ApplicantDomain;
|
using Domains.ApplicantDomain;
|
||||||
using FluentValidation;
|
using FluentValidation;
|
||||||
|
|
||||||
namespace ApplicationLayer.Services.AuthServices.Requests.Validation
|
namespace ApplicationLayer.Services.AuthServices.Requests.Validation;
|
||||||
|
|
||||||
|
public class PassportValidator : AbstractValidator<Passport>
|
||||||
{
|
{
|
||||||
public class PassportValidator : AbstractValidator<Passport>
|
public PassportValidator(IDateTimeProvider dateTimeProvider)
|
||||||
{
|
{
|
||||||
public PassportValidator(IDateTimeProvider dateTimeProvider)
|
|
||||||
{
|
|
||||||
RuleFor(r => r.Issuer)
|
RuleFor(r => r.Issuer)
|
||||||
.NotEmpty()
|
.NotEmpty()
|
||||||
.WithMessage("Passport issuer can not be empty")
|
.WithMessage("Passport issuer can not be empty")
|
||||||
@@ -33,5 +33,4 @@ namespace ApplicationLayer.Services.AuthServices.Requests.Validation
|
|||||||
.LessThanOrEqualTo(dateTimeProvider.Now())
|
.LessThanOrEqualTo(dateTimeProvider.Now())
|
||||||
.WithMessage("Passport issue date must be in past");
|
.WithMessage("Passport issue date must be in past");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@@ -2,12 +2,12 @@
|
|||||||
using Domains;
|
using Domains;
|
||||||
using FluentValidation;
|
using FluentValidation;
|
||||||
|
|
||||||
namespace ApplicationLayer.Services.AuthServices.Requests.Validation
|
namespace ApplicationLayer.Services.AuthServices.Requests.Validation;
|
||||||
|
|
||||||
|
public class PlaceOfWorkModelValidator : AbstractValidator<PlaceOfWorkModel>
|
||||||
{
|
{
|
||||||
public class PlaceOfWorkModelValidator : AbstractValidator<PlaceOfWorkModel>
|
public PlaceOfWorkModelValidator()
|
||||||
{
|
{
|
||||||
public PlaceOfWorkModelValidator()
|
|
||||||
{
|
|
||||||
RuleFor(p => p.Name)
|
RuleFor(p => p.Name)
|
||||||
.NotEmpty()
|
.NotEmpty()
|
||||||
.WithMessage("Place of work name can not be empty")
|
.WithMessage("Place of work name can not be empty")
|
||||||
@@ -46,5 +46,4 @@ namespace ApplicationLayer.Services.AuthServices.Requests.Validation
|
|||||||
.MaximumLength(ConfigurationConstraints.CountryNameLength)
|
.MaximumLength(ConfigurationConstraints.CountryNameLength)
|
||||||
.WithMessage($"Building of place of work length must be less than {ConfigurationConstraints.BuildingNumberLength}");
|
.WithMessage($"Building of place of work length must be less than {ConfigurationConstraints.BuildingNumberLength}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@@ -5,17 +5,17 @@ using Domains;
|
|||||||
using Domains.ApplicantDomain;
|
using Domains.ApplicantDomain;
|
||||||
using FluentValidation;
|
using FluentValidation;
|
||||||
|
|
||||||
namespace ApplicationLayer.Services.AuthServices.Requests.Validation
|
namespace ApplicationLayer.Services.AuthServices.Requests.Validation;
|
||||||
|
|
||||||
|
public class RegisterApplicantRequestValidator : AbstractValidator<RegisterApplicantRequest>
|
||||||
{
|
{
|
||||||
public class RegisterApplicantRequestValidator : AbstractValidator<RegisterApplicantRequest>
|
public RegisterApplicantRequestValidator(
|
||||||
|
IDateTimeProvider dateTimeProvider,
|
||||||
|
IValidator<Name> nameValidator,
|
||||||
|
IValidator<AuthData> authDataValidator,
|
||||||
|
IValidator<Passport> passportValidator,
|
||||||
|
IValidator<PlaceOfWorkModel> placeOfWorkModelValidator)
|
||||||
{
|
{
|
||||||
public RegisterApplicantRequestValidator(
|
|
||||||
IDateTimeProvider dateTimeProvider,
|
|
||||||
IValidator<Name> nameValidator,
|
|
||||||
IValidator<AuthData> authDataValidator,
|
|
||||||
IValidator<Passport> passportValidator,
|
|
||||||
IValidator<PlaceOfWorkModel> placeOfWorkModelValidator)
|
|
||||||
{
|
|
||||||
RuleFor(r => r.AuthData)
|
RuleFor(r => r.AuthData)
|
||||||
.SetValidator(authDataValidator);
|
.SetValidator(authDataValidator);
|
||||||
|
|
||||||
@@ -74,5 +74,4 @@ namespace ApplicationLayer.Services.AuthServices.Requests.Validation
|
|||||||
RuleFor(r => r.PlaceOfWork)
|
RuleFor(r => r.PlaceOfWork)
|
||||||
.SetValidator(placeOfWorkModelValidator);
|
.SetValidator(placeOfWorkModelValidator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@@ -1,23 +1,22 @@
|
|||||||
using ApplicationLayer.Services.Users.Requests;
|
using ApplicationLayer.Services.Users.Requests;
|
||||||
using Domains.Users;
|
using Domains.Users;
|
||||||
|
|
||||||
namespace ApplicationLayer.Services.Users
|
namespace ApplicationLayer.Services.Users;
|
||||||
|
|
||||||
|
/// user accounts service
|
||||||
|
public interface IUsersService
|
||||||
{
|
{
|
||||||
/// user accounts service
|
/// Returns all user accounts with role of approving authority
|
||||||
public interface IUsersService
|
/// <param name="cancellationToken">Cancellation token</param>
|
||||||
{
|
Task<List<User>> GetAuthoritiesAccountsAsync(CancellationToken cancellationToken);
|
||||||
/// Returns all user accounts with role of approving authority
|
|
||||||
/// <param name="cancellationToken">Cancellation token</param>
|
|
||||||
Task<List<User>> GetAuthoritiesAccountsAsync(CancellationToken cancellationToken);
|
|
||||||
|
|
||||||
/// Changes authentication data for an account
|
/// Changes authentication data for an account
|
||||||
/// <param name="request"> Request object with identifier of user and new authentication data</param>
|
/// <param name="request"> Request object with identifier of user and new authentication data</param>
|
||||||
/// <param name="cancellationToken">Cancellation token</param>
|
/// <param name="cancellationToken">Cancellation token</param>
|
||||||
Task ChangeAccountAuthDataAsync(ChangeUserAuthDataRequest request, CancellationToken cancellationToken);
|
Task ChangeAccountAuthDataAsync(ChangeUserAuthDataRequest request, CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// Removes user account
|
/// Removes user account
|
||||||
/// <param name="userId">Identifier of account</param>
|
/// <param name="userId">Identifier of account</param>
|
||||||
/// <param name="cancellationToken">Cancellation token</param>
|
/// <param name="cancellationToken">Cancellation token</param>
|
||||||
Task RemoveUserAccount(Guid userId, CancellationToken cancellationToken);
|
Task RemoveUserAccount(Guid userId, CancellationToken cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
using ApplicationLayer.Services.AuthServices.Common;
|
using ApplicationLayer.Services.AuthServices.Common;
|
||||||
|
|
||||||
namespace ApplicationLayer.Services.Users.Requests
|
namespace ApplicationLayer.Services.Users.Requests;
|
||||||
{
|
|
||||||
public record ChangeUserAuthDataRequest(Guid UserId, AuthData NewAuthData);
|
public record ChangeUserAuthDataRequest(Guid UserId, AuthData NewAuthData);
|
||||||
}
|
|
||||||
@@ -3,17 +3,17 @@ using ApplicationLayer.Services.AuthServices.NeededServices;
|
|||||||
using ApplicationLayer.Services.Users.Requests;
|
using ApplicationLayer.Services.Users.Requests;
|
||||||
using Domains.Users;
|
using Domains.Users;
|
||||||
|
|
||||||
namespace ApplicationLayer.Services.Users
|
namespace ApplicationLayer.Services.Users;
|
||||||
|
|
||||||
|
public class UsersService(IUsersRepository users, IUnitOfWork unitOfWork) : IUsersService
|
||||||
{
|
{
|
||||||
public class UsersService(IUsersRepository users, IUnitOfWork unitOfWork) : IUsersService
|
async Task<List<User>> IUsersService.GetAuthoritiesAccountsAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
async Task<List<User>> IUsersService.GetAuthoritiesAccountsAsync(CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
return await users.GetAllOfRoleAsync(Role.ApprovingAuthority, cancellationToken);
|
return await users.GetAllOfRoleAsync(Role.ApprovingAuthority, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
async Task IUsersService.ChangeAccountAuthDataAsync(ChangeUserAuthDataRequest request, CancellationToken cancellationToken)
|
async Task IUsersService.ChangeAccountAuthDataAsync(ChangeUserAuthDataRequest request, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var user = await users.GetByIdAsync(request.UserId, cancellationToken);
|
var user = await users.GetByIdAsync(request.UserId, cancellationToken);
|
||||||
|
|
||||||
user.Email = request.NewAuthData.Email;
|
user.Email = request.NewAuthData.Email;
|
||||||
@@ -23,12 +23,11 @@ namespace ApplicationLayer.Services.Users
|
|||||||
await unitOfWork.SaveAsync(cancellationToken);
|
await unitOfWork.SaveAsync(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
async Task IUsersService.RemoveUserAccount(Guid userId, CancellationToken cancellationToken)
|
async Task IUsersService.RemoveUserAccount(Guid userId, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var user = await users.GetByIdAsync(userId, cancellationToken);
|
var user = await users.GetByIdAsync(userId, cancellationToken);
|
||||||
users.Remove(user);
|
users.Remove(user);
|
||||||
|
|
||||||
await unitOfWork.SaveAsync(cancellationToken);
|
await unitOfWork.SaveAsync(cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
using ApplicationLayer.GeneralExceptions;
|
using ApplicationLayer.GeneralExceptions;
|
||||||
|
|
||||||
namespace ApplicationLayer.Services.VisaApplications.Exceptions
|
namespace ApplicationLayer.Services.VisaApplications.Exceptions;
|
||||||
{
|
|
||||||
public class ApplicationAlreadyProcessedException() : ApiException("This application already processed or closed by applicant.");
|
public class ApplicationAlreadyProcessedException() : ApiException("This application already processed or closed by applicant.");
|
||||||
}
|
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
namespace ApplicationLayer.Services.VisaApplications.Models
|
namespace ApplicationLayer.Services.VisaApplications.Models;
|
||||||
|
|
||||||
|
public enum AuthorityRequestStatuses
|
||||||
{
|
{
|
||||||
public enum AuthorityRequestStatuses
|
Approved,
|
||||||
{
|
Rejected
|
||||||
Approved,
|
}
|
||||||
Rejected
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,44 +1,43 @@
|
|||||||
using Domains.VisaApplicationDomain;
|
using Domains.VisaApplicationDomain;
|
||||||
|
|
||||||
namespace ApplicationLayer.Services.VisaApplications.Models
|
namespace ApplicationLayer.Services.VisaApplications.Models;
|
||||||
|
|
||||||
|
/// Model of <see cref="VisaApplication"/>
|
||||||
|
public class VisaApplicationModelForApplicant
|
||||||
{
|
{
|
||||||
/// Model of <see cref="VisaApplication"/>
|
/// <inheritdoc cref="VisaApplication.Id"/>
|
||||||
public class VisaApplicationModelForApplicant
|
public Guid Id { get; set; }
|
||||||
{
|
|
||||||
/// <inheritdoc cref="VisaApplication.Id"/>
|
|
||||||
public Guid Id { get; set; }
|
|
||||||
|
|
||||||
/// <inheritdoc cref="VisaApplication.Status"/>
|
/// <inheritdoc cref="VisaApplication.Status"/>
|
||||||
public ApplicationStatus Status { get; set; }
|
public ApplicationStatus Status { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc cref="VisaApplication.ReentryPermit"/>
|
/// <inheritdoc cref="VisaApplication.ReentryPermit"/>
|
||||||
public ReentryPermit? ReentryPermit { get; set; }
|
public ReentryPermit? ReentryPermit { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc cref="VisaApplication.DestinationCountry"/>
|
/// <inheritdoc cref="VisaApplication.DestinationCountry"/>
|
||||||
public string DestinationCountry { get; set; } = null!;
|
public string DestinationCountry { get; set; } = null!;
|
||||||
|
|
||||||
/// <inheritdoc cref="VisaApplication.PastVisas"/>
|
/// <inheritdoc cref="VisaApplication.PastVisas"/>
|
||||||
public List<PastVisa> PastVisas { get; set; } = null!;
|
public List<PastVisa> PastVisas { get; set; } = null!;
|
||||||
|
|
||||||
/// <inheritdoc cref="VisaApplication.PermissionToDestCountry"/>
|
/// <inheritdoc cref="VisaApplication.PermissionToDestCountry"/>
|
||||||
public PermissionToDestCountry? PermissionToDestCountry { get; set; }
|
public PermissionToDestCountry? PermissionToDestCountry { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc cref="VisaApplication.PastVisits"/>
|
/// <inheritdoc cref="VisaApplication.PastVisits"/>
|
||||||
public List<PastVisit> PastVisits { get; set; } = null!;
|
public List<PastVisit> PastVisits { get; set; } = null!;
|
||||||
|
|
||||||
/// <inheritdoc cref="VisaApplication.VisaCategory"/>
|
/// <inheritdoc cref="VisaApplication.VisaCategory"/>
|
||||||
public VisaCategory VisaCategory { get; set; }
|
public VisaCategory VisaCategory { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc cref="VisaApplication.ForGroup"/>
|
/// <inheritdoc cref="VisaApplication.ForGroup"/>
|
||||||
public bool ForGroup { get; set; }
|
public bool ForGroup { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc cref="VisaApplication.RequestedNumberOfEntries"/>
|
/// <inheritdoc cref="VisaApplication.RequestedNumberOfEntries"/>
|
||||||
public RequestedNumberOfEntries RequestedNumberOfEntries { get; set; }
|
public RequestedNumberOfEntries RequestedNumberOfEntries { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc cref="VisaApplication.RequestDate"/>
|
/// <inheritdoc cref="VisaApplication.RequestDate"/>
|
||||||
public DateTime RequestDate { get; set; }
|
public DateTime RequestDate { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc cref="VisaApplication.ValidDaysRequested"/>
|
/// <inheritdoc cref="VisaApplication.ValidDaysRequested"/>
|
||||||
public int ValidDaysRequested { get; set; }
|
public int ValidDaysRequested { get; set; }
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@@ -1,47 +1,46 @@
|
|||||||
using ApplicationLayer.Services.Applicants.Models;
|
using ApplicationLayer.Services.Applicants.Models;
|
||||||
using Domains.VisaApplicationDomain;
|
using Domains.VisaApplicationDomain;
|
||||||
|
|
||||||
namespace ApplicationLayer.Services.VisaApplications.Models
|
namespace ApplicationLayer.Services.VisaApplications.Models;
|
||||||
|
|
||||||
|
/// Model of <see cref="VisaApplication"/> with applicant property
|
||||||
|
public class VisaApplicationModelForAuthority
|
||||||
{
|
{
|
||||||
/// Model of <see cref="VisaApplication"/> with applicant property
|
/// <inheritdoc cref="VisaApplication.Id"/>
|
||||||
public class VisaApplicationModelForAuthority
|
public Guid Id { get; set; }
|
||||||
{
|
|
||||||
/// <inheritdoc cref="VisaApplication.Id"/>
|
|
||||||
public Guid Id { get; set; }
|
|
||||||
|
|
||||||
/// Applicant of application
|
/// Applicant of application
|
||||||
public ApplicantModel Applicant { get; set; } = null!;
|
public ApplicantModel Applicant { get; set; } = null!;
|
||||||
|
|
||||||
/// <inheritdoc cref="VisaApplication.Status"/>
|
/// <inheritdoc cref="VisaApplication.Status"/>
|
||||||
public ApplicationStatus Status { get; set; }
|
public ApplicationStatus Status { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc cref="VisaApplication.ReentryPermit"/>
|
/// <inheritdoc cref="VisaApplication.ReentryPermit"/>
|
||||||
public ReentryPermit? ReentryPermit { get; set; }
|
public ReentryPermit? ReentryPermit { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc cref="VisaApplication.DestinationCountry"/>
|
/// <inheritdoc cref="VisaApplication.DestinationCountry"/>
|
||||||
public string DestinationCountry { get; set; } = null!;
|
public string DestinationCountry { get; set; } = null!;
|
||||||
|
|
||||||
/// <inheritdoc cref="VisaApplication.PastVisas"/>
|
/// <inheritdoc cref="VisaApplication.PastVisas"/>
|
||||||
public List<PastVisa> PastVisas { get; set; } = null!;
|
public List<PastVisa> PastVisas { get; set; } = null!;
|
||||||
|
|
||||||
/// <inheritdoc cref="VisaApplication.PermissionToDestCountry"/>
|
/// <inheritdoc cref="VisaApplication.PermissionToDestCountry"/>
|
||||||
public PermissionToDestCountry? PermissionToDestCountry { get; set; }
|
public PermissionToDestCountry? PermissionToDestCountry { get; set; }
|
||||||
|
|
||||||
public List<PastVisit> PastVisits { get; set; } = null!;
|
public List<PastVisit> PastVisits { get; set; } = null!;
|
||||||
|
|
||||||
/// <inheritdoc cref="VisaApplication.VisaCategory"/>
|
/// <inheritdoc cref="VisaApplication.VisaCategory"/>
|
||||||
public VisaCategory VisaCategory { get; set; }
|
public VisaCategory VisaCategory { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc cref="VisaApplication.ForGroup"/>
|
/// <inheritdoc cref="VisaApplication.ForGroup"/>
|
||||||
public bool ForGroup { get; set; }
|
public bool ForGroup { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc cref="VisaApplication.RequestedNumberOfEntries"/>
|
/// <inheritdoc cref="VisaApplication.RequestedNumberOfEntries"/>
|
||||||
public RequestedNumberOfEntries RequestedNumberOfEntries { get; set; }
|
public RequestedNumberOfEntries RequestedNumberOfEntries { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc cref="VisaApplication.RequestDate"/>
|
/// <inheritdoc cref="VisaApplication.RequestDate"/>
|
||||||
public DateTime RequestDate { get; set; }
|
public DateTime RequestDate { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc cref="VisaApplication.ValidDaysRequested"/>
|
/// <inheritdoc cref="VisaApplication.ValidDaysRequested"/>
|
||||||
public int ValidDaysRequested { get; set; }
|
public int ValidDaysRequested { get; set; }
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@@ -2,12 +2,12 @@
|
|||||||
using Domains.VisaApplicationDomain;
|
using Domains.VisaApplicationDomain;
|
||||||
using FluentValidation;
|
using FluentValidation;
|
||||||
|
|
||||||
namespace ApplicationLayer.Services.VisaApplications.Requests.Validation
|
namespace ApplicationLayer.Services.VisaApplications.Requests.Validation;
|
||||||
|
|
||||||
|
public class PastVisaValidator : AbstractValidator<PastVisa>
|
||||||
{
|
{
|
||||||
public class PastVisaValidator : AbstractValidator<PastVisa>
|
public PastVisaValidator(IDateTimeProvider dateTimeProvider)
|
||||||
{
|
{
|
||||||
public PastVisaValidator(IDateTimeProvider dateTimeProvider)
|
|
||||||
{
|
|
||||||
RuleFor(v => v.ExpirationDate)
|
RuleFor(v => v.ExpirationDate)
|
||||||
.NotEmpty()
|
.NotEmpty()
|
||||||
.WithMessage("Expiration date of past visa can not be empty")
|
.WithMessage("Expiration date of past visa can not be empty")
|
||||||
@@ -24,5 +24,4 @@ namespace ApplicationLayer.Services.VisaApplications.Requests.Validation
|
|||||||
.NotEmpty()
|
.NotEmpty()
|
||||||
.WithMessage("Name of past visa can not be empty");
|
.WithMessage("Name of past visa can not be empty");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@@ -3,12 +3,12 @@ using Domains;
|
|||||||
using Domains.VisaApplicationDomain;
|
using Domains.VisaApplicationDomain;
|
||||||
using FluentValidation;
|
using FluentValidation;
|
||||||
|
|
||||||
namespace ApplicationLayer.Services.VisaApplications.Requests.Validation
|
namespace ApplicationLayer.Services.VisaApplications.Requests.Validation;
|
||||||
|
|
||||||
|
public class PastVisitValidator : AbstractValidator<PastVisit>
|
||||||
{
|
{
|
||||||
public class PastVisitValidator : AbstractValidator<PastVisit>
|
public PastVisitValidator(IDateTimeProvider dateTimeProvider)
|
||||||
{
|
{
|
||||||
public PastVisitValidator(IDateTimeProvider dateTimeProvider)
|
|
||||||
{
|
|
||||||
RuleFor(v => v.StartDate)
|
RuleFor(v => v.StartDate)
|
||||||
.NotEmpty()
|
.NotEmpty()
|
||||||
.WithMessage("Start date of past visit can not be empty")
|
.WithMessage("Start date of past visit can not be empty")
|
||||||
@@ -27,5 +27,4 @@ namespace ApplicationLayer.Services.VisaApplications.Requests.Validation
|
|||||||
.MaximumLength(ConfigurationConstraints.CountryNameLength)
|
.MaximumLength(ConfigurationConstraints.CountryNameLength)
|
||||||
.WithMessage($"Destination Country of past visit length must be less than {ConfigurationConstraints.CountryNameLength}");
|
.WithMessage($"Destination Country of past visit length must be less than {ConfigurationConstraints.CountryNameLength}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@@ -3,12 +3,12 @@ using Domains;
|
|||||||
using Domains.VisaApplicationDomain;
|
using Domains.VisaApplicationDomain;
|
||||||
using FluentValidation;
|
using FluentValidation;
|
||||||
|
|
||||||
namespace ApplicationLayer.Services.VisaApplications.Requests.Validation
|
namespace ApplicationLayer.Services.VisaApplications.Requests.Validation;
|
||||||
|
|
||||||
|
public class PermissionToDestCountryValidator : AbstractValidator<PermissionToDestCountry?>
|
||||||
{
|
{
|
||||||
public class PermissionToDestCountryValidator : AbstractValidator<PermissionToDestCountry?>
|
public PermissionToDestCountryValidator(IDateTimeProvider dateTimeProvider)
|
||||||
{
|
{
|
||||||
public PermissionToDestCountryValidator(IDateTimeProvider dateTimeProvider)
|
|
||||||
{
|
|
||||||
RuleFor(p => p!.ExpirationDate)
|
RuleFor(p => p!.ExpirationDate)
|
||||||
.NotEmpty()
|
.NotEmpty()
|
||||||
.WithMessage("Expiration date of permission to destination Country can not be empty")
|
.WithMessage("Expiration date of permission to destination Country can not be empty")
|
||||||
@@ -21,5 +21,4 @@ namespace ApplicationLayer.Services.VisaApplications.Requests.Validation
|
|||||||
.MaximumLength(ConfigurationConstraints.IssuerNameLength)
|
.MaximumLength(ConfigurationConstraints.IssuerNameLength)
|
||||||
.WithMessage($"Issuer of permission to destination Country length must be less than {ConfigurationConstraints.IssuerNameLength}");
|
.WithMessage($"Issuer of permission to destination Country length must be less than {ConfigurationConstraints.IssuerNameLength}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@@ -3,12 +3,12 @@ using Domains;
|
|||||||
using Domains.VisaApplicationDomain;
|
using Domains.VisaApplicationDomain;
|
||||||
using FluentValidation;
|
using FluentValidation;
|
||||||
|
|
||||||
namespace ApplicationLayer.Services.VisaApplications.Requests.Validation
|
namespace ApplicationLayer.Services.VisaApplications.Requests.Validation;
|
||||||
|
|
||||||
|
public class ReentryPermitValidator : AbstractValidator<ReentryPermit?>
|
||||||
{
|
{
|
||||||
public class ReentryPermitValidator : AbstractValidator<ReentryPermit?>
|
public ReentryPermitValidator(IDateTimeProvider dateTimeProvider)
|
||||||
{
|
{
|
||||||
public ReentryPermitValidator(IDateTimeProvider dateTimeProvider)
|
|
||||||
{
|
|
||||||
RuleFor(p => p!.Number)
|
RuleFor(p => p!.Number)
|
||||||
.NotEmpty()
|
.NotEmpty()
|
||||||
.WithMessage("Re-entry permit number can not be empty")
|
.WithMessage("Re-entry permit number can not be empty")
|
||||||
@@ -21,5 +21,4 @@ namespace ApplicationLayer.Services.VisaApplications.Requests.Validation
|
|||||||
.GreaterThan(dateTimeProvider.Now())
|
.GreaterThan(dateTimeProvider.Now())
|
||||||
.WithMessage("Re-entry permit must not be expired");
|
.WithMessage("Re-entry permit must not be expired");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@@ -4,51 +4,50 @@ using Domains;
|
|||||||
using Domains.VisaApplicationDomain;
|
using Domains.VisaApplicationDomain;
|
||||||
using FluentValidation;
|
using FluentValidation;
|
||||||
|
|
||||||
namespace ApplicationLayer.Services.VisaApplications.Requests.Validation
|
namespace ApplicationLayer.Services.VisaApplications.Requests.Validation;
|
||||||
|
|
||||||
|
public class VisaApplicationCreateRequestValidator : AbstractValidator<VisaApplicationCreateRequest>
|
||||||
{
|
{
|
||||||
public class VisaApplicationCreateRequestValidator : AbstractValidator<VisaApplicationCreateRequest>
|
public VisaApplicationCreateRequestValidator(
|
||||||
|
IValidator<ReentryPermit?> reentryPermitValidator,
|
||||||
|
IValidator<PastVisa> pastVisaValidator,
|
||||||
|
IValidator<PermissionToDestCountry?> permissionToDestCountryValidator,
|
||||||
|
IValidator<PastVisit> pastVisitValidator,
|
||||||
|
IApplicantsRepository applicants,
|
||||||
|
IUserIdProvider userIdProvider)
|
||||||
{
|
{
|
||||||
public VisaApplicationCreateRequestValidator(
|
RuleFor(r => r.ReentryPermit)
|
||||||
IValidator<ReentryPermit?> reentryPermitValidator,
|
.NotEmpty()
|
||||||
IValidator<PastVisa> pastVisaValidator,
|
.WithMessage("Non-residents must provide re-entry permission")
|
||||||
IValidator<PermissionToDestCountry?> permissionToDestCountryValidator,
|
.SetValidator(reentryPermitValidator)
|
||||||
IValidator<PastVisit> pastVisitValidator,
|
.WhenAsync(async (r, ct) =>
|
||||||
IApplicantsRepository applicants,
|
await applicants.IsApplicantNonResidentByUserId(userIdProvider.GetUserId(), ct));
|
||||||
IUserIdProvider userIdProvider)
|
|
||||||
{
|
|
||||||
RuleFor(r => r.ReentryPermit)
|
|
||||||
.NotEmpty()
|
|
||||||
.WithMessage("Non-residents must provide re-entry permission")
|
|
||||||
.SetValidator(reentryPermitValidator)
|
|
||||||
.WhenAsync(async (r, ct) =>
|
|
||||||
await applicants.IsApplicantNonResidentByUserId(userIdProvider.GetUserId(), ct));
|
|
||||||
|
|
||||||
RuleFor(r => r.DestinationCountry)
|
RuleFor(r => r.DestinationCountry)
|
||||||
.NotEmpty()
|
.NotEmpty()
|
||||||
.WithMessage("Destination country can not be empty");
|
.WithMessage("Destination country can not be empty");
|
||||||
|
|
||||||
RuleFor(r => r.VisaCategory)
|
RuleFor(r => r.VisaCategory)
|
||||||
.IsInEnum();
|
.IsInEnum();
|
||||||
|
|
||||||
RuleFor(r => r.RequestedNumberOfEntries)
|
RuleFor(r => r.RequestedNumberOfEntries)
|
||||||
.IsInEnum();
|
.IsInEnum();
|
||||||
|
|
||||||
RuleFor(r => r.ValidDaysRequested)
|
RuleFor(r => r.ValidDaysRequested)
|
||||||
.GreaterThan(0)
|
.GreaterThan(0)
|
||||||
.WithMessage($"Valid days requested should be positive number and less than {ConfigurationConstraints.MaxValidDays}")
|
.WithMessage($"Valid days requested should be positive number and less than {ConfigurationConstraints.MaxValidDays}")
|
||||||
.LessThanOrEqualTo(ConfigurationConstraints.MaxValidDays)
|
.LessThanOrEqualTo(ConfigurationConstraints.MaxValidDays)
|
||||||
.WithMessage($"Valid days requested must be less than or equal to {ConfigurationConstraints.MaxValidDays}");
|
.WithMessage($"Valid days requested must be less than or equal to {ConfigurationConstraints.MaxValidDays}");
|
||||||
|
|
||||||
RuleForEach(r => r.PastVisas)
|
RuleForEach(r => r.PastVisas)
|
||||||
.SetValidator(pastVisaValidator);
|
.SetValidator(pastVisaValidator);
|
||||||
|
|
||||||
When(r => r.VisaCategory == VisaCategory.Transit,
|
When(r => r.VisaCategory == VisaCategory.Transit,
|
||||||
() =>
|
() =>
|
||||||
RuleFor(r => r.PermissionToDestCountry)
|
RuleFor(r => r.PermissionToDestCountry)
|
||||||
.SetValidator(permissionToDestCountryValidator));
|
.SetValidator(permissionToDestCountryValidator));
|
||||||
|
|
||||||
RuleForEach(r => r.PastVisits)
|
RuleForEach(r => r.PastVisits)
|
||||||
.SetValidator(pastVisitValidator);
|
.SetValidator(pastVisitValidator);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,24 +1,23 @@
|
|||||||
namespace Domains
|
namespace Domains;
|
||||||
|
|
||||||
|
public static class ConfigurationConstraints
|
||||||
{
|
{
|
||||||
public static class ConfigurationConstraints
|
public const int CityNameLength = 70;
|
||||||
{
|
public const int CountryNameLength = 70;
|
||||||
public const int CityNameLength = 70;
|
public const int CitizenshipLength = 30;
|
||||||
public const int CountryNameLength = 70;
|
public const int ReentryPermitNumberLength = 25;
|
||||||
public const int CitizenshipLength = 30;
|
public const int IssuerNameLength = 200;
|
||||||
public const int ReentryPermitNumberLength = 25;
|
public const int VisaNameLength = 70;
|
||||||
public const int IssuerNameLength = 200;
|
public const int StreetNameLength = 100;
|
||||||
public const int VisaNameLength = 70;
|
public const int PlaceOfWorkNameLength = 200;
|
||||||
public const int StreetNameLength = 100;
|
public const int NameLength = 50;
|
||||||
public const int PlaceOfWorkNameLength = 200;
|
public const int BuildingNumberLength = 10;
|
||||||
public const int NameLength = 50;
|
public const int PassportNumberLength = 20;
|
||||||
public const int BuildingNumberLength = 10;
|
public const int PhoneNumberLength = 13;
|
||||||
public const int PassportNumberLength = 20;
|
public const int PhoneNumberMinLength = 11;
|
||||||
public const int PhoneNumberLength = 13;
|
public const int EmailLength = 254;
|
||||||
public const int PhoneNumberMinLength = 11;
|
public const int PasswordLength = 50;
|
||||||
public const int EmailLength = 254;
|
public const int ApplicantMinAge = 14;
|
||||||
public const int PasswordLength = 50;
|
public const int JobTitleLength = 50;
|
||||||
public const int ApplicantMinAge = 14;
|
public const int MaxValidDays = 90;
|
||||||
public const int JobTitleLength = 50;
|
}
|
||||||
public const int MaxValidDays = 90;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,13 +1,12 @@
|
|||||||
namespace Domains.Users
|
namespace Domains.Users;
|
||||||
|
|
||||||
|
/// Role of <see cref="User"/>
|
||||||
|
public enum Role
|
||||||
{
|
{
|
||||||
/// Role of <see cref="User"/>
|
/// Requests visa applications
|
||||||
public enum Role
|
Applicant,
|
||||||
{
|
/// Approves or declines applications
|
||||||
/// Requests visa applications
|
ApprovingAuthority,
|
||||||
Applicant,
|
/// Manages approving authorities
|
||||||
/// Approves or declines applications
|
Admin
|
||||||
ApprovingAuthority,
|
}
|
||||||
/// Manages approving authorities
|
|
||||||
Admin
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +1,13 @@
|
|||||||
namespace Domains.Users
|
namespace Domains.Users;
|
||||||
|
|
||||||
|
public class User : IEntity
|
||||||
{
|
{
|
||||||
public class User : IEntity
|
/// Unique Identifier of <see cref="User"/>
|
||||||
{
|
public Guid Id { get; private set; } = Guid.NewGuid();
|
||||||
/// Unique Identifier of <see cref="User"/>
|
|
||||||
public Guid Id { get; private set; } = Guid.NewGuid();
|
|
||||||
|
|
||||||
public Role Role { get; set; }
|
public Role Role { get; set; }
|
||||||
|
|
||||||
public string Email { get; set; } = null!;
|
public string Email { get; set; } = null!;
|
||||||
|
|
||||||
public string Password { get; set; } = null!;
|
public string Password { get; set; } = null!;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@@ -1,12 +1,11 @@
|
|||||||
namespace Domains.VisaApplicationDomain
|
namespace Domains.VisaApplicationDomain;
|
||||||
|
|
||||||
|
public enum ApplicationStatus
|
||||||
{
|
{
|
||||||
public enum ApplicationStatus
|
/// Waits for approve
|
||||||
{
|
Pending,
|
||||||
/// Waits for approve
|
Approved,
|
||||||
Pending,
|
Rejected,
|
||||||
Approved,
|
/// Closed by applicant
|
||||||
Rejected,
|
Closed
|
||||||
/// Closed by applicant
|
}
|
||||||
Closed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -3,12 +3,12 @@ using ApplicationLayer.InfrastructureServicesInterfaces;
|
|||||||
using ApplicationLayer.Services.AuthServices.NeededServices;
|
using ApplicationLayer.Services.AuthServices.NeededServices;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
namespace Infrastructure.Auth
|
namespace Infrastructure.Auth;
|
||||||
|
|
||||||
|
public static class ServiceCollectionsExtensions
|
||||||
{
|
{
|
||||||
public static class ServiceCollectionsExtensions
|
public static IServiceCollection AddTokenGenerator(this IServiceCollection services, TokenGeneratorOptions options)
|
||||||
{
|
{
|
||||||
public static IServiceCollection AddTokenGenerator(this IServiceCollection services, TokenGeneratorOptions options)
|
|
||||||
{
|
|
||||||
services.AddSingleton<JwtSecurityTokenHandler>();
|
services.AddSingleton<JwtSecurityTokenHandler>();
|
||||||
services.AddSingleton<ITokenGenerator, TokenGenerator>(provider =>
|
services.AddSingleton<ITokenGenerator, TokenGenerator>(provider =>
|
||||||
{
|
{
|
||||||
@@ -20,5 +20,4 @@ namespace Infrastructure.Auth
|
|||||||
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@@ -4,27 +4,26 @@ using ApplicationLayer.InfrastructureServicesInterfaces;
|
|||||||
using ApplicationLayer.Services.AuthServices.NeededServices;
|
using ApplicationLayer.Services.AuthServices.NeededServices;
|
||||||
using Domains.Users;
|
using Domains.Users;
|
||||||
|
|
||||||
namespace Infrastructure.Auth
|
namespace Infrastructure.Auth;
|
||||||
|
|
||||||
|
public class TokenGenerator(TokenGeneratorOptions options, JwtSecurityTokenHandler tokenHandler, IDateTimeProvider dateTimeProvider)
|
||||||
|
: ITokenGenerator
|
||||||
{
|
{
|
||||||
public class TokenGenerator(TokenGeneratorOptions options, JwtSecurityTokenHandler tokenHandler, IDateTimeProvider dateTimeProvider)
|
public string CreateToken(User user)
|
||||||
: ITokenGenerator
|
|
||||||
{
|
{
|
||||||
public string CreateToken(User user)
|
var claims = new List<Claim>
|
||||||
{
|
{
|
||||||
var claims = new List<Claim>
|
new(ClaimTypes.Role, user.Role.ToString()),
|
||||||
{
|
new(ClaimTypes.NameIdentifier, user.Id.ToString())
|
||||||
new(ClaimTypes.Role, user.Role.ToString()),
|
};
|
||||||
new(ClaimTypes.NameIdentifier, user.Id.ToString())
|
|
||||||
};
|
|
||||||
|
|
||||||
var token = new JwtSecurityToken(
|
var token = new JwtSecurityToken(
|
||||||
issuer: options.Issuer,
|
issuer: options.Issuer,
|
||||||
audience: options.Audience,
|
audience: options.Audience,
|
||||||
expires: dateTimeProvider.Now().Add(options.ValidTime),
|
expires: dateTimeProvider.Now().Add(options.ValidTime),
|
||||||
signingCredentials: options.Credentials,
|
signingCredentials: options.Credentials,
|
||||||
claims: claims);
|
claims: claims);
|
||||||
|
|
||||||
return tokenHandler.WriteToken(token);
|
return tokenHandler.WriteToken(token);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
using Microsoft.IdentityModel.Tokens;
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
|
||||||
namespace Infrastructure.Auth
|
namespace Infrastructure.Auth;
|
||||||
{
|
|
||||||
public record TokenGeneratorOptions(string Issuer, string Audience, TimeSpan ValidTime, SigningCredentials Credentials);
|
public record TokenGeneratorOptions(string Issuer, string Audience, TimeSpan ValidTime, SigningCredentials Credentials);
|
||||||
}
|
|
||||||
@@ -3,12 +3,12 @@ using ApplicationLayer.Services.AuthServices.Requests;
|
|||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
using Domains.ApplicantDomain;
|
using Domains.ApplicantDomain;
|
||||||
|
|
||||||
namespace Infrastructure.Automapper.Profiles
|
namespace Infrastructure.Automapper.Profiles;
|
||||||
|
|
||||||
|
public class ApplicantProfile : Profile
|
||||||
{
|
{
|
||||||
public class ApplicantProfile : Profile
|
public ApplicantProfile()
|
||||||
{
|
{
|
||||||
public ApplicantProfile()
|
|
||||||
{
|
|
||||||
CreateMap<Applicant, ApplicantModel>(MemberList.Destination);
|
CreateMap<Applicant, ApplicantModel>(MemberList.Destination);
|
||||||
|
|
||||||
CreateMap<RegisterApplicantRequest, Applicant>(MemberList.Destination)
|
CreateMap<RegisterApplicantRequest, Applicant>(MemberList.Destination)
|
||||||
@@ -16,5 +16,4 @@ namespace Infrastructure.Automapper.Profiles
|
|||||||
.ForMember(a => a.Name,
|
.ForMember(a => a.Name,
|
||||||
opts => opts.MapFrom(r => r.ApplicantName));
|
opts => opts.MapFrom(r => r.ApplicantName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@@ -2,15 +2,14 @@
|
|||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
using Domains.ApplicantDomain;
|
using Domains.ApplicantDomain;
|
||||||
|
|
||||||
namespace Infrastructure.Automapper.Profiles
|
namespace Infrastructure.Automapper.Profiles;
|
||||||
|
|
||||||
|
public class PlaceOfWorkProfile : Profile
|
||||||
{
|
{
|
||||||
public class PlaceOfWorkProfile : Profile
|
public PlaceOfWorkProfile()
|
||||||
{
|
{
|
||||||
public PlaceOfWorkProfile()
|
|
||||||
{
|
|
||||||
CreateMap<PlaceOfWorkModel, PlaceOfWork>(MemberList.Destination)
|
CreateMap<PlaceOfWorkModel, PlaceOfWork>(MemberList.Destination)
|
||||||
.ForMember(p => p.Id,
|
.ForMember(p => p.Id,
|
||||||
opts => opts.UseDestinationValue());
|
opts => opts.UseDestinationValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@@ -2,15 +2,14 @@
|
|||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
using Domains.Users;
|
using Domains.Users;
|
||||||
|
|
||||||
namespace Infrastructure.Automapper.Profiles
|
namespace Infrastructure.Automapper.Profiles;
|
||||||
|
|
||||||
|
public class UserProfile : Profile
|
||||||
{
|
{
|
||||||
public class UserProfile : Profile
|
public UserProfile()
|
||||||
{
|
{
|
||||||
public UserProfile()
|
|
||||||
{
|
|
||||||
CreateMap<AuthData, User>(MemberList.Destination)
|
CreateMap<AuthData, User>(MemberList.Destination)
|
||||||
.ForMember(u => u.Role,
|
.ForMember(u => u.Role,
|
||||||
opts => opts.Ignore());
|
opts => opts.Ignore());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@@ -3,12 +3,12 @@ using ApplicationLayer.Services.VisaApplications.Requests;
|
|||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
using Domains.VisaApplicationDomain;
|
using Domains.VisaApplicationDomain;
|
||||||
|
|
||||||
namespace Infrastructure.Automapper.Profiles
|
namespace Infrastructure.Automapper.Profiles;
|
||||||
|
|
||||||
|
public class VisaApplicationProfile : Profile
|
||||||
{
|
{
|
||||||
public class VisaApplicationProfile : Profile
|
public VisaApplicationProfile()
|
||||||
{
|
{
|
||||||
public VisaApplicationProfile()
|
|
||||||
{
|
|
||||||
CreateMap<VisaApplication, VisaApplicationModelForApplicant>(MemberList.Destination);
|
CreateMap<VisaApplication, VisaApplicationModelForApplicant>(MemberList.Destination);
|
||||||
|
|
||||||
CreateMap<VisaApplication, VisaApplicationModelForAuthority>(MemberList.Destination)
|
CreateMap<VisaApplication, VisaApplicationModelForAuthority>(MemberList.Destination)
|
||||||
@@ -21,5 +21,4 @@ namespace Infrastructure.Automapper.Profiles
|
|||||||
.ForMember(va => va.ApplicantId,
|
.ForMember(va => va.ApplicantId,
|
||||||
opts => opts.Ignore());
|
opts => opts.Ignore());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
using ApplicationLayer.InfrastructureServicesInterfaces;
|
using ApplicationLayer.InfrastructureServicesInterfaces;
|
||||||
|
|
||||||
namespace Infrastructure.Common
|
namespace Infrastructure.Common;
|
||||||
|
|
||||||
|
/// Implements <see cref="IDateTimeProvider"/>
|
||||||
|
public class DateTimeProvider : IDateTimeProvider
|
||||||
{
|
{
|
||||||
/// Implements <see cref="IDateTimeProvider"/>
|
DateTime IDateTimeProvider.Now() => DateTime.Now;
|
||||||
public class DateTimeProvider : IDateTimeProvider
|
}
|
||||||
{
|
|
||||||
DateTime IDateTimeProvider.Now() => DateTime.Now;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,12 +2,12 @@
|
|||||||
using ApplicationLayer.InfrastructureServicesInterfaces;
|
using ApplicationLayer.InfrastructureServicesInterfaces;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
|
||||||
namespace Infrastructure.Common
|
namespace Infrastructure.Common;
|
||||||
|
|
||||||
|
public class UserIdProvider(IHttpContextAccessor contextAccessor) : IUserIdProvider
|
||||||
{
|
{
|
||||||
public class UserIdProvider(IHttpContextAccessor contextAccessor) : IUserIdProvider
|
Guid IUserIdProvider.GetUserId()
|
||||||
{
|
{
|
||||||
Guid IUserIdProvider.GetUserId()
|
|
||||||
{
|
|
||||||
var claim = contextAccessor.HttpContext!.User.Claims.SingleOrDefault(claim => claim.Type == ClaimTypes.NameIdentifier);
|
var claim = contextAccessor.HttpContext!.User.Claims.SingleOrDefault(claim => claim.Type == ClaimTypes.NameIdentifier);
|
||||||
if (claim is null)
|
if (claim is null)
|
||||||
{
|
{
|
||||||
@@ -15,5 +15,4 @@ namespace Infrastructure.Common
|
|||||||
}
|
}
|
||||||
return Guid.Parse(claim.Value);
|
return Guid.Parse(claim.Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
using ApplicationLayer.Services.GeneralExceptions;
|
using ApplicationLayer.Services.GeneralExceptions;
|
||||||
|
|
||||||
namespace Infrastructure.Database.Applicants.Repositories.Exceptions
|
namespace Infrastructure.Database.Applicants.Repositories.Exceptions;
|
||||||
{
|
|
||||||
public class ApplicantNotFoundByUserIdException() : EntityNotFoundException("Applicant not found.");
|
public class ApplicantNotFoundByUserIdException() : EntityNotFoundException("Applicant not found.");
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,12 +3,12 @@ using Domains.Users;
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
|
||||||
namespace Infrastructure.Database.Users.Configuration
|
namespace Infrastructure.Database.Users.Configuration;
|
||||||
|
|
||||||
|
public class UserConfiguration : IEntityTypeConfiguration<User>
|
||||||
{
|
{
|
||||||
public class UserConfiguration : IEntityTypeConfiguration<User>
|
public void Configure(EntityTypeBuilder<User> entity)
|
||||||
{
|
{
|
||||||
public void Configure(EntityTypeBuilder<User> entity)
|
|
||||||
{
|
|
||||||
entity.Property(u => u.Email)
|
entity.Property(u => u.Email)
|
||||||
.IsUnicode(false)
|
.IsUnicode(false)
|
||||||
.HasMaxLength(ConfigurationConstraints.EmailLength);
|
.HasMaxLength(ConfigurationConstraints.EmailLength);
|
||||||
@@ -19,5 +19,4 @@ namespace Infrastructure.Database.Users.Configuration
|
|||||||
.IsUnicode(false)
|
.IsUnicode(false)
|
||||||
.HasMaxLength(ConfigurationConstraints.PasswordLength);
|
.HasMaxLength(ConfigurationConstraints.PasswordLength);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@@ -3,20 +3,19 @@ using Domains.Users;
|
|||||||
using Infrastructure.Database.Generic;
|
using Infrastructure.Database.Generic;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace Infrastructure.Database.Users.Repositories
|
namespace Infrastructure.Database.Users.Repositories;
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IUsersRepository"/>
|
||||||
|
public class UsersRepository(IGenericReader reader, IGenericWriter writer)
|
||||||
|
: GenericRepository<User>(reader, writer), IUsersRepository
|
||||||
{
|
{
|
||||||
/// <inheritdoc cref="IUsersRepository"/>
|
async Task<User?> IUsersRepository.FindByEmailAsync(string email, CancellationToken cancellationToken)
|
||||||
public class UsersRepository(IGenericReader reader, IGenericWriter writer)
|
|
||||||
: GenericRepository<User>(reader, writer), IUsersRepository
|
|
||||||
{
|
{
|
||||||
async Task<User?> IUsersRepository.FindByEmailAsync(string email, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
return await LoadDomain().SingleOrDefaultAsync(u => u.Email == email, cancellationToken);
|
return await LoadDomain().SingleOrDefaultAsync(u => u.Email == email, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
async Task<List<User>> IUsersRepository.GetAllOfRoleAsync(Role role, CancellationToken cancellationToken)
|
async Task<List<User>> IUsersRepository.GetAllOfRoleAsync(Role role, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return await LoadDomain().Where(u => u.Role == role).ToListAsync(cancellationToken);
|
return await LoadDomain().Where(u => u.Role == role).ToListAsync(cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@@ -2,15 +2,14 @@
|
|||||||
using Domains.VisaApplicationDomain;
|
using Domains.VisaApplicationDomain;
|
||||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
|
||||||
namespace Infrastructure.Database.VisaApplications.Configuration
|
namespace Infrastructure.Database.VisaApplications.Configuration;
|
||||||
|
|
||||||
|
public static class PastVisitConfiguration<T> where T : class, IEntity
|
||||||
{
|
{
|
||||||
public static class PastVisitConfiguration<T> where T : class, IEntity
|
public static void Configure(OwnedNavigationBuilder<T, PastVisit> entity)
|
||||||
{
|
{
|
||||||
public static void Configure(OwnedNavigationBuilder<T, PastVisit> entity)
|
|
||||||
{
|
|
||||||
entity.Property(pv => pv.DestinationCountry)
|
entity.Property(pv => pv.DestinationCountry)
|
||||||
.IsUnicode(false)
|
.IsUnicode(false)
|
||||||
.HasMaxLength(ConfigurationConstraints.CountryNameLength);
|
.HasMaxLength(ConfigurationConstraints.CountryNameLength);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
using ApplicationLayer.Services.GeneralExceptions;
|
using ApplicationLayer.Services.GeneralExceptions;
|
||||||
|
|
||||||
namespace Infrastructure.Database.VisaApplications.Repositories.Exceptions
|
namespace Infrastructure.Database.VisaApplications.Repositories.Exceptions;
|
||||||
{
|
|
||||||
public class ApplicationNotFoundByApplicantAndApplicationIdException(Guid applicationId)
|
public class ApplicationNotFoundByApplicantAndApplicationIdException(Guid applicationId)
|
||||||
: EntityNotFoundException($"Application with id {applicationId} not found for authenticated user");
|
: EntityNotFoundException($"Application with id {applicationId} not found for authenticated user");
|
||||||
}
|
|
||||||
@@ -2,13 +2,13 @@
|
|||||||
using Microsoft.OpenApi.Models;
|
using Microsoft.OpenApi.Models;
|
||||||
using Swashbuckle.AspNetCore.SwaggerGen;
|
using Swashbuckle.AspNetCore.SwaggerGen;
|
||||||
|
|
||||||
namespace SchengenVisaApi.Common
|
namespace SchengenVisaApi.Common;
|
||||||
|
|
||||||
|
/// Adds auth for swagger
|
||||||
|
public class ConfigureSwaggerOptions : IConfigureOptions<SwaggerGenOptions>
|
||||||
{
|
{
|
||||||
/// Adds auth for swagger
|
void IConfigureOptions<SwaggerGenOptions>.Configure(SwaggerGenOptions options)
|
||||||
public class ConfigureSwaggerOptions : IConfigureOptions<SwaggerGenOptions>
|
|
||||||
{
|
{
|
||||||
void IConfigureOptions<SwaggerGenOptions>.Configure(SwaggerGenOptions options)
|
|
||||||
{
|
|
||||||
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
|
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
|
||||||
{
|
{
|
||||||
In = ParameterLocation.Header,
|
In = ParameterLocation.Header,
|
||||||
@@ -34,5 +34,4 @@ namespace SchengenVisaApi.Common
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@@ -1,12 +1,9 @@
|
|||||||
namespace SchengenVisaApi.Common
|
namespace SchengenVisaApi.Common;
|
||||||
{
|
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
public static class PolicyConstants
|
public static class PolicyConstants
|
||||||
{
|
{
|
||||||
public const string AdminPolicy = "AdminPolicy";
|
public const string AdminPolicy = "AdminPolicy";
|
||||||
public const string ApplicantPolicy = "ApplicantPolicy";
|
public const string ApplicantPolicy = "ApplicantPolicy";
|
||||||
public const string ApprovingAuthorityPolicy = "ApprovingAuthorityPolicy";
|
public const string ApprovingAuthorityPolicy = "ApprovingAuthorityPolicy";
|
||||||
}
|
|
||||||
#pragma warning enable CS1591
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
#pragma warning enable CS1591
|
||||||
@@ -10,106 +10,105 @@ using Microsoft.AspNetCore.Authorization;
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using SchengenVisaApi.Common;
|
using SchengenVisaApi.Common;
|
||||||
|
|
||||||
namespace SchengenVisaApi.Controllers
|
namespace SchengenVisaApi.Controllers;
|
||||||
|
|
||||||
|
///<summary> Controller for user-auth and registration </summary>
|
||||||
|
[ApiController]
|
||||||
|
[Route("users")]
|
||||||
|
public class UsersController(
|
||||||
|
IRegisterService registerService,
|
||||||
|
ILoginService loginService,
|
||||||
|
IUsersService usersService,
|
||||||
|
IValidator<RegisterApplicantRequest> registerApplicantRequestValidator,
|
||||||
|
IValidator<AuthData> authDataValidator) : ControllerBase
|
||||||
{
|
{
|
||||||
///<summary> Controller for user-auth and registration </summary>
|
/// <summary> Adds applicant with user account to DB </summary>
|
||||||
[ApiController]
|
[HttpPost]
|
||||||
[Route("users")]
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
public class UsersController(
|
[ProducesResponseType(StatusCodes.Status409Conflict)]
|
||||||
IRegisterService registerService,
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||||
ILoginService loginService,
|
[Route("register")]
|
||||||
IUsersService usersService,
|
public async Task<IActionResult> Register(RegisterApplicantRequest request, CancellationToken cancellationToken)
|
||||||
IValidator<RegisterApplicantRequest> registerApplicantRequestValidator,
|
|
||||||
IValidator<AuthData> authDataValidator) : ControllerBase
|
|
||||||
{
|
{
|
||||||
/// <summary> Adds applicant with user account to DB </summary>
|
await registerApplicantRequestValidator.ValidateAndThrowAsync(request, cancellationToken);
|
||||||
[HttpPost]
|
|
||||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
|
||||||
[ProducesResponseType(StatusCodes.Status409Conflict)]
|
|
||||||
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
|
||||||
[Route("register")]
|
|
||||||
public async Task<IActionResult> Register(RegisterApplicantRequest request, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
await registerApplicantRequestValidator.ValidateAndThrowAsync(request, cancellationToken);
|
|
||||||
|
|
||||||
await registerService.RegisterApplicant(request, cancellationToken);
|
await registerService.RegisterApplicant(request, cancellationToken);
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary> Adds approving authority with user account to DB </summary>
|
|
||||||
///<remarks> Accessible only for admins </remarks>
|
|
||||||
[HttpPost]
|
|
||||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
|
||||||
[ProducesResponseType(StatusCodes.Status409Conflict)]
|
|
||||||
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
|
||||||
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
|
||||||
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
|
||||||
[Route("authorities")]
|
|
||||||
[Authorize(policy: PolicyConstants.AdminPolicy)]
|
|
||||||
public async Task<IActionResult> RegisterAuthority(RegisterRequest request, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
await authDataValidator.ValidateAndThrowAsync(request.AuthData, cancellationToken);
|
|
||||||
|
|
||||||
await registerService.RegisterAuthority(request, cancellationToken);
|
|
||||||
return Ok();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary> Returns JWT-token for authentication </summary>
|
|
||||||
[HttpGet]
|
|
||||||
[ProducesResponseType<string>(StatusCodes.Status200OK)]
|
|
||||||
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
|
||||||
[Route("login")]
|
|
||||||
public async Task<IActionResult> Login(string email, string password, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var result = await loginService.LoginAsync(email, password, cancellationToken);
|
|
||||||
return Ok(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary> Returns list of authority accounts </summary>
|
|
||||||
/// <remarks> Accessible only for admins </remarks>
|
|
||||||
[HttpGet]
|
|
||||||
[ProducesResponseType<List<User>>(StatusCodes.Status200OK)]
|
|
||||||
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
|
||||||
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
|
||||||
[Route("authorities")]
|
|
||||||
[Authorize(policy: PolicyConstants.AdminPolicy)]
|
|
||||||
public async Task<IActionResult> GetAuthorityAccounts(CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var result = await usersService.GetAuthoritiesAccountsAsync(cancellationToken);
|
|
||||||
return Ok(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary> Changes authority's account authentication data </summary>
|
|
||||||
/// <remarks> Accessible only for admins </remarks>
|
|
||||||
[HttpPut]
|
|
||||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
|
||||||
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
|
||||||
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
|
||||||
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
|
||||||
[Route("authorities/{authorityAccountId:guid}")]
|
|
||||||
[Authorize(policy: PolicyConstants.AdminPolicy)]
|
|
||||||
public async Task<IActionResult> ChangeAuthorityAuthData(Guid authorityAccountId, AuthData authData, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
await authDataValidator.ValidateAndThrowAsync(authData, cancellationToken);
|
|
||||||
|
|
||||||
await usersService.ChangeAccountAuthDataAsync(new ChangeUserAuthDataRequest(authorityAccountId, authData), cancellationToken);
|
|
||||||
return Ok();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary> Removes authority's account authentication data </summary>
|
|
||||||
/// <remarks> Accessible only for admins </remarks>
|
|
||||||
[HttpDelete]
|
|
||||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
|
||||||
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
|
||||||
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
|
||||||
[Route("authorities/{authorityAccountId:guid}")]
|
|
||||||
[Authorize(policy: PolicyConstants.AdminPolicy)]
|
|
||||||
public async Task<IActionResult> RemoveAuthorityAccount(Guid authorityAccountId, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
await usersService.RemoveUserAccount(authorityAccountId, cancellationToken);
|
|
||||||
return Ok();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/// <summary> Adds approving authority with user account to DB </summary>
|
||||||
|
///<remarks> Accessible only for admins </remarks>
|
||||||
|
[HttpPost]
|
||||||
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status409Conflict)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||||
|
[Route("authorities")]
|
||||||
|
[Authorize(policy: PolicyConstants.AdminPolicy)]
|
||||||
|
public async Task<IActionResult> RegisterAuthority(RegisterRequest request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
await authDataValidator.ValidateAndThrowAsync(request.AuthData, cancellationToken);
|
||||||
|
|
||||||
|
await registerService.RegisterAuthority(request, cancellationToken);
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Returns JWT-token for authentication </summary>
|
||||||
|
[HttpGet]
|
||||||
|
[ProducesResponseType<string>(StatusCodes.Status200OK)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||||
|
[Route("login")]
|
||||||
|
public async Task<IActionResult> Login(string email, string password, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var result = await loginService.LoginAsync(email, password, cancellationToken);
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Returns list of authority accounts </summary>
|
||||||
|
/// <remarks> Accessible only for admins </remarks>
|
||||||
|
[HttpGet]
|
||||||
|
[ProducesResponseType<List<User>>(StatusCodes.Status200OK)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
||||||
|
[Route("authorities")]
|
||||||
|
[Authorize(policy: PolicyConstants.AdminPolicy)]
|
||||||
|
public async Task<IActionResult> GetAuthorityAccounts(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var result = await usersService.GetAuthoritiesAccountsAsync(cancellationToken);
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Changes authority's account authentication data </summary>
|
||||||
|
/// <remarks> Accessible only for admins </remarks>
|
||||||
|
[HttpPut]
|
||||||
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||||
|
[Route("authorities/{authorityAccountId:guid}")]
|
||||||
|
[Authorize(policy: PolicyConstants.AdminPolicy)]
|
||||||
|
public async Task<IActionResult> ChangeAuthorityAuthData(Guid authorityAccountId, AuthData authData, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
await authDataValidator.ValidateAndThrowAsync(authData, cancellationToken);
|
||||||
|
|
||||||
|
await usersService.ChangeAccountAuthDataAsync(new ChangeUserAuthDataRequest(authorityAccountId, authData), cancellationToken);
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Removes authority's account authentication data </summary>
|
||||||
|
/// <remarks> Accessible only for admins </remarks>
|
||||||
|
[HttpDelete]
|
||||||
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
||||||
|
[Route("authorities/{authorityAccountId:guid}")]
|
||||||
|
[Authorize(policy: PolicyConstants.AdminPolicy)]
|
||||||
|
public async Task<IActionResult> RemoveAuthorityAccount(Guid authorityAccountId, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
await usersService.RemoveUserAccount(authorityAccountId, cancellationToken);
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,67 +6,66 @@ using FluentValidation;
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Mvc.Filters;
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
|
|
||||||
namespace SchengenVisaApi.ExceptionFilters
|
namespace SchengenVisaApi.ExceptionFilters;
|
||||||
|
|
||||||
|
/// Handles <see cref="ApiException"/>
|
||||||
|
public class GlobalExceptionsFilter : IAsyncExceptionFilter
|
||||||
{
|
{
|
||||||
/// Handles <see cref="ApiException"/>
|
/// <inheritdoc cref="IExceptionFilter.OnException"/>
|
||||||
public class GlobalExceptionsFilter : IAsyncExceptionFilter
|
public async Task OnExceptionAsync(ExceptionContext context)
|
||||||
{
|
{
|
||||||
/// <inheritdoc cref="IExceptionFilter.OnException"/>
|
var exception = context.Exception;
|
||||||
public async Task OnExceptionAsync(ExceptionContext context)
|
var problemDetails = new ProblemDetails();
|
||||||
|
|
||||||
|
switch (exception)
|
||||||
{
|
{
|
||||||
var exception = context.Exception;
|
case ValidationException validationException:
|
||||||
var problemDetails = new ProblemDetails();
|
problemDetails.Extensions.Add("Errors", validationException.Errors.Select(e => e.ErrorMessage));
|
||||||
|
problemDetails.Detail = "Validation errors occured";
|
||||||
|
problemDetails.Status = StatusCodes.Status400BadRequest;
|
||||||
|
problemDetails.Title = "Bad request";
|
||||||
|
problemDetails.Type = "https://datatracker.ietf.org/doc/html/rfc7231#section-6.5.1";
|
||||||
|
break;
|
||||||
|
case ApiException:
|
||||||
|
problemDetails.Detail = exception.Message;
|
||||||
|
switch (exception)
|
||||||
|
{
|
||||||
|
case EntityNotFoundException:
|
||||||
|
problemDetails.Status = StatusCodes.Status404NotFound;
|
||||||
|
problemDetails.Title = "Requested entity not found";
|
||||||
|
problemDetails.Type = "https://datatracker.ietf.org/doc/html/rfc7231#section-6.5.4";
|
||||||
|
break;
|
||||||
|
case IncorrectLoginDataException:
|
||||||
|
problemDetails.Status = StatusCodes.Status403Forbidden;
|
||||||
|
problemDetails.Title = "Auth failed";
|
||||||
|
problemDetails.Type = "https://datatracker.ietf.org/doc/html/rfc7231#section-6.5.3";
|
||||||
|
break;
|
||||||
|
case AlreadyExistsException:
|
||||||
|
problemDetails.Status = StatusCodes.Status409Conflict;
|
||||||
|
problemDetails.Title = "Already exists";
|
||||||
|
problemDetails.Type = "https://datatracker.ietf.org/doc/html/rfc7231#section-6.5.8";
|
||||||
|
break;
|
||||||
|
case ApplicationAlreadyProcessedException:
|
||||||
|
problemDetails.Status = StatusCodes.Status409Conflict;
|
||||||
|
problemDetails.Title = "Already processed";
|
||||||
|
problemDetails.Type = "https://datatracker.ietf.org/doc/html/rfc7231#section-6.5.8";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
problemDetails.Status = StatusCodes.Status400BadRequest;
|
||||||
|
problemDetails.Title = "Bad request";
|
||||||
|
problemDetails.Type = "https://datatracker.ietf.org/doc/html/rfc7231#section-6.5.1";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
switch (exception)
|
break;
|
||||||
{
|
default:
|
||||||
case ValidationException validationException:
|
problemDetails.Status = StatusCodes.Status500InternalServerError;
|
||||||
problemDetails.Extensions.Add("Errors", validationException.Errors.Select(e => e.ErrorMessage));
|
problemDetails.Title = "An unhandled error occured";
|
||||||
problemDetails.Detail = "Validation errors occured";
|
problemDetails.Type = "https://datatracker.ietf.org/doc/html/rfc7231#section-6.6.1";
|
||||||
problemDetails.Status = StatusCodes.Status400BadRequest;
|
break;
|
||||||
problemDetails.Title = "Bad request";
|
|
||||||
problemDetails.Type = "https://datatracker.ietf.org/doc/html/rfc7231#section-6.5.1";
|
|
||||||
break;
|
|
||||||
case ApiException:
|
|
||||||
problemDetails.Detail = exception.Message;
|
|
||||||
switch (exception)
|
|
||||||
{
|
|
||||||
case EntityNotFoundException:
|
|
||||||
problemDetails.Status = StatusCodes.Status404NotFound;
|
|
||||||
problemDetails.Title = "Requested entity not found";
|
|
||||||
problemDetails.Type = "https://datatracker.ietf.org/doc/html/rfc7231#section-6.5.4";
|
|
||||||
break;
|
|
||||||
case IncorrectLoginDataException:
|
|
||||||
problemDetails.Status = StatusCodes.Status403Forbidden;
|
|
||||||
problemDetails.Title = "Auth failed";
|
|
||||||
problemDetails.Type = "https://datatracker.ietf.org/doc/html/rfc7231#section-6.5.3";
|
|
||||||
break;
|
|
||||||
case AlreadyExistsException:
|
|
||||||
problemDetails.Status = StatusCodes.Status409Conflict;
|
|
||||||
problemDetails.Title = "Already exists";
|
|
||||||
problemDetails.Type = "https://datatracker.ietf.org/doc/html/rfc7231#section-6.5.8";
|
|
||||||
break;
|
|
||||||
case ApplicationAlreadyProcessedException:
|
|
||||||
problemDetails.Status = StatusCodes.Status409Conflict;
|
|
||||||
problemDetails.Title = "Already processed";
|
|
||||||
problemDetails.Type = "https://datatracker.ietf.org/doc/html/rfc7231#section-6.5.8";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
problemDetails.Status = StatusCodes.Status400BadRequest;
|
|
||||||
problemDetails.Title = "Bad request";
|
|
||||||
problemDetails.Type = "https://datatracker.ietf.org/doc/html/rfc7231#section-6.5.1";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
problemDetails.Status = StatusCodes.Status500InternalServerError;
|
|
||||||
problemDetails.Title = "An unhandled error occured";
|
|
||||||
problemDetails.Type = "https://datatracker.ietf.org/doc/html/rfc7231#section-6.6.1";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
await Results.Problem(problemDetails).ExecuteAsync(context.HttpContext);
|
|
||||||
context.ExceptionHandled = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await Results.Problem(problemDetails).ExecuteAsync(context.HttpContext);
|
||||||
|
context.ExceptionHandled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user