file-scoped namespaces
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
namespace ApplicationLayer.GeneralExceptions
|
||||
{
|
||||
public class AlreadyExistsException(string message) : ApiException(message);
|
||||
}
|
||||
namespace ApplicationLayer.GeneralExceptions;
|
||||
|
||||
public class AlreadyExistsException(string message) : ApiException(message);
|
||||
@@ -1,4 +1,3 @@
|
||||
namespace ApplicationLayer.GeneralExceptions
|
||||
{
|
||||
public class ApiException(string message) : Exception(message);
|
||||
}
|
||||
namespace ApplicationLayer.GeneralExceptions;
|
||||
|
||||
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;
|
||||
|
||||
namespace ApplicationLayer.Services.Applicants.Models
|
||||
namespace ApplicationLayer.Services.Applicants.Models;
|
||||
|
||||
/// Model of <see cref="Applicant"/>
|
||||
public class ApplicantModel
|
||||
{
|
||||
/// Model of <see cref="Applicant"/>
|
||||
public class ApplicantModel
|
||||
{
|
||||
/// <inheritdoc cref="Applicant.Name"/>
|
||||
public Name Name { get; set; } = null!;
|
||||
/// <inheritdoc cref="Applicant.Name"/>
|
||||
public Name Name { get; set; } = null!;
|
||||
|
||||
/// <inheritdoc cref="Applicant.Passport"/>
|
||||
public Passport Passport { get; set; } = null!;
|
||||
/// <inheritdoc cref="Applicant.Passport"/>
|
||||
public Passport Passport { get; set; } = null!;
|
||||
|
||||
/// <inheritdoc cref="Applicant.BirthDate"/>
|
||||
public DateTime BirthDate { get; set; }
|
||||
/// <inheritdoc cref="Applicant.BirthDate"/>
|
||||
public DateTime BirthDate { get; set; }
|
||||
|
||||
/// <inheritdoc cref="Applicant.CountryOfBirth"/>
|
||||
public string CountryOfBirth { get; set; } = null!;
|
||||
/// <inheritdoc cref="Applicant.CountryOfBirth"/>
|
||||
public string CountryOfBirth { get; set; } = null!;
|
||||
|
||||
/// <inheritdoc cref="Applicant.CityOfBirth"/>
|
||||
public string CityOfBirth { get; set; } = null!;
|
||||
/// <inheritdoc cref="Applicant.CityOfBirth"/>
|
||||
public string CityOfBirth { get; set; } = null!;
|
||||
|
||||
/// <inheritdoc cref="Applicant.Citizenship"/>
|
||||
public string Citizenship { get; set; } = null!;
|
||||
/// <inheritdoc cref="Applicant.Citizenship"/>
|
||||
public string Citizenship { get; set; } = null!;
|
||||
|
||||
/// <inheritdoc cref="Applicant.CitizenshipByBirth"/>
|
||||
public string CitizenshipByBirth { get; set; } = null!;
|
||||
/// <inheritdoc cref="Applicant.CitizenshipByBirth"/>
|
||||
public string CitizenshipByBirth { get; set; } = null!;
|
||||
|
||||
/// <inheritdoc cref="Applicant.Gender"/>
|
||||
public Gender Gender { get; set; }
|
||||
/// <inheritdoc cref="Applicant.Gender"/>
|
||||
public Gender Gender { get; set; }
|
||||
|
||||
/// <inheritdoc cref="Applicant.MaritalStatus"/>
|
||||
public MaritalStatus MaritalStatus { get; set; }
|
||||
/// <inheritdoc cref="Applicant.MaritalStatus"/>
|
||||
public MaritalStatus MaritalStatus { get; set; }
|
||||
|
||||
/// <inheritdoc cref="Applicant.FatherName"/>
|
||||
public Name FatherName { get; set; } = null!;
|
||||
/// <inheritdoc cref="Applicant.FatherName"/>
|
||||
public Name FatherName { get; set; } = null!;
|
||||
|
||||
/// <inheritdoc cref="Applicant.MotherName"/>
|
||||
public Name MotherName { get; set; } = null!;
|
||||
/// <inheritdoc cref="Applicant.MotherName"/>
|
||||
public Name MotherName { get; set; } = null!;
|
||||
|
||||
/// <inheritdoc cref="Applicant.JobTitle"/>
|
||||
public string JobTitle { get; set; } = null!;
|
||||
/// <inheritdoc cref="Applicant.JobTitle"/>
|
||||
public string JobTitle { get; set; } = null!;
|
||||
|
||||
/// <inheritdoc cref="Applicant.PlaceOfWork"/>
|
||||
public PlaceOfWork PlaceOfWork { get; set; } = null!;
|
||||
/// <inheritdoc cref="Applicant.PlaceOfWork"/>
|
||||
public PlaceOfWork PlaceOfWork { get; set; } = null!;
|
||||
|
||||
/// <inheritdoc cref="Applicant.IsNonResident"/>
|
||||
public bool IsNonResident { get; set; }
|
||||
}
|
||||
}
|
||||
/// <inheritdoc cref="Applicant.IsNonResident"/>
|
||||
public bool IsNonResident { get; set; }
|
||||
}
|
||||
@@ -1,16 +1,15 @@
|
||||
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
|
||||
public Address Address { get; set; } = null!;
|
||||
/// Address of hirer
|
||||
public Address Address { get; set; } = null!;
|
||||
|
||||
/// Phone number of hirer
|
||||
public string PhoneNum { get; set; } = null!;
|
||||
}
|
||||
}
|
||||
/// Phone number of hirer
|
||||
public string PhoneNum { get; set; } = null!;
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
namespace ApplicationLayer.Services.AuthServices.Common
|
||||
{
|
||||
public record AuthData(string Email, string Password);
|
||||
}
|
||||
namespace ApplicationLayer.Services.AuthServices.Common;
|
||||
|
||||
public record AuthData(string Email, string Password);
|
||||
@@ -2,12 +2,12 @@
|
||||
using ApplicationLayer.Services.AuthServices.NeededServices;
|
||||
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")
|
||||
{
|
||||
var admin = new User { Role = Role.Admin };
|
||||
@@ -23,5 +23,4 @@ namespace ApplicationLayer.Services.AuthServices.LoginService
|
||||
|
||||
return tokenGenerator.CreateToken(user);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
using ApplicationLayer.GeneralExceptions;
|
||||
|
||||
namespace ApplicationLayer.Services.AuthServices.LoginService.Exceptions
|
||||
{
|
||||
public class IncorrectLoginDataException() : ApiException("Incorrect email or password");
|
||||
}
|
||||
namespace ApplicationLayer.Services.AuthServices.LoginService.Exceptions;
|
||||
|
||||
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
|
||||
public interface ILoginService
|
||||
{
|
||||
/// Handle login request
|
||||
/// <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.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"/>
|
||||
public class LoginService(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)
|
||||
{
|
||||
var user = await users.FindByEmailAsync(email, cancellationToken);
|
||||
if (user is null || user.Password != password)
|
||||
{
|
||||
@@ -16,5 +16,4 @@ namespace ApplicationLayer.Services.AuthServices.LoginService
|
||||
|
||||
return tokenGenerator.CreateToken(user);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,8 @@
|
||||
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 Domains.Users;
|
||||
|
||||
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);
|
||||
namespace ApplicationLayer.Services.AuthServices.NeededServices;
|
||||
|
||||
/// 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);
|
||||
}
|
||||
}
|
||||
/// 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
|
||||
/// <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;
|
||||
|
||||
namespace ApplicationLayer.Services.AuthServices.RegisterService
|
||||
{
|
||||
/// Handles register request
|
||||
public interface IRegisterService
|
||||
{
|
||||
/// Handle <see cref="RegisterApplicantRequest"/>
|
||||
Task RegisterApplicant(RegisterApplicantRequest request, CancellationToken cancellationToken);
|
||||
namespace ApplicationLayer.Services.AuthServices.RegisterService;
|
||||
|
||||
/// Handles <see cref="RegisterRequest"/> and adds approving authority account
|
||||
Task RegisterAuthority(RegisterRequest request, CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
||||
/// 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
|
||||
Task RegisterAuthority(RegisterRequest request, CancellationToken cancellationToken);
|
||||
}
|
||||
@@ -6,37 +6,36 @@ using AutoMapper;
|
||||
using Domains.ApplicantDomain;
|
||||
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"/>
|
||||
public class RegisterService(
|
||||
IUsersRepository users,
|
||||
IApplicantsRepository applicants,
|
||||
IUnitOfWork unitOfWork,
|
||||
IMapper mapper) : IRegisterService
|
||||
async Task IRegisterService.RegisterApplicant(RegisterApplicantRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
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);
|
||||
applicant.UserId = user.Id;
|
||||
var applicant = mapper.Map<Applicant>(request);
|
||||
applicant.UserId = user.Id;
|
||||
|
||||
await users.AddAsync(user, cancellationToken);
|
||||
await applicants.AddAsync(applicant, cancellationToken);
|
||||
await users.AddAsync(user, cancellationToken);
|
||||
await applicants.AddAsync(applicant, 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);
|
||||
}
|
||||
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 Domains.ApplicantDomain;
|
||||
|
||||
namespace ApplicationLayer.Services.AuthServices.Requests
|
||||
{
|
||||
public record RegisterApplicantRequest(
|
||||
AuthData AuthData,
|
||||
Name ApplicantName,
|
||||
Passport Passport,
|
||||
DateTime BirthDate,
|
||||
string CityOfBirth,
|
||||
string CountryOfBirth,
|
||||
string Citizenship,
|
||||
string CitizenshipByBirth,
|
||||
Gender Gender,
|
||||
MaritalStatus MaritalStatus,
|
||||
Name FatherName,
|
||||
Name MotherName,
|
||||
string JobTitle,
|
||||
PlaceOfWorkModel PlaceOfWork,
|
||||
bool IsNonResident) : RegisterRequest(AuthData);
|
||||
}
|
||||
namespace ApplicationLayer.Services.AuthServices.Requests;
|
||||
|
||||
public record RegisterApplicantRequest(
|
||||
AuthData AuthData,
|
||||
Name ApplicantName,
|
||||
Passport Passport,
|
||||
DateTime BirthDate,
|
||||
string CityOfBirth,
|
||||
string CountryOfBirth,
|
||||
string Citizenship,
|
||||
string CitizenshipByBirth,
|
||||
Gender Gender,
|
||||
MaritalStatus MaritalStatus,
|
||||
Name FatherName,
|
||||
Name MotherName,
|
||||
string JobTitle,
|
||||
PlaceOfWorkModel PlaceOfWork,
|
||||
bool IsNonResident) : RegisterRequest(AuthData);
|
||||
@@ -1,6 +1,5 @@
|
||||
using ApplicationLayer.Services.AuthServices.Common;
|
||||
|
||||
namespace ApplicationLayer.Services.AuthServices.Requests
|
||||
{
|
||||
public record RegisterRequest(AuthData AuthData);
|
||||
}
|
||||
namespace ApplicationLayer.Services.AuthServices.Requests;
|
||||
|
||||
public record RegisterRequest(AuthData AuthData);
|
||||
@@ -3,12 +3,12 @@ using ApplicationLayer.Services.AuthServices.NeededServices;
|
||||
using Domains;
|
||||
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)
|
||||
.NotEmpty()
|
||||
.WithMessage("Email can not be empty")
|
||||
@@ -28,5 +28,4 @@ namespace ApplicationLayer.Services.AuthServices.Requests.Validation
|
||||
.MaximumLength(ConfigurationConstraints.PasswordLength)
|
||||
.WithMessage($"Password length must be less than {ConfigurationConstraints.PasswordLength}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,12 +2,12 @@
|
||||
using Domains.ApplicantDomain;
|
||||
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)
|
||||
.NotEmpty()
|
||||
.WithMessage("First Name can not be empty")
|
||||
@@ -24,5 +24,4 @@ namespace ApplicationLayer.Services.AuthServices.Requests.Validation
|
||||
.MaximumLength(ConfigurationConstraints.NameLength)
|
||||
.WithMessage($"Patronymic length must be less than {ConfigurationConstraints.NameLength}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,12 +3,12 @@ using Domains;
|
||||
using Domains.ApplicantDomain;
|
||||
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)
|
||||
.NotEmpty()
|
||||
.WithMessage("Passport issuer can not be empty")
|
||||
@@ -33,5 +33,4 @@ namespace ApplicationLayer.Services.AuthServices.Requests.Validation
|
||||
.LessThanOrEqualTo(dateTimeProvider.Now())
|
||||
.WithMessage("Passport issue date must be in past");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,12 +2,12 @@
|
||||
using Domains;
|
||||
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)
|
||||
.NotEmpty()
|
||||
.WithMessage("Place of work name can not be empty")
|
||||
@@ -46,5 +46,4 @@ namespace ApplicationLayer.Services.AuthServices.Requests.Validation
|
||||
.MaximumLength(ConfigurationConstraints.CountryNameLength)
|
||||
.WithMessage($"Building of place of work length must be less than {ConfigurationConstraints.BuildingNumberLength}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,17 +5,17 @@ using Domains;
|
||||
using Domains.ApplicantDomain;
|
||||
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)
|
||||
.SetValidator(authDataValidator);
|
||||
|
||||
@@ -74,5 +74,4 @@ namespace ApplicationLayer.Services.AuthServices.Requests.Validation
|
||||
RuleFor(r => r.PlaceOfWork)
|
||||
.SetValidator(placeOfWorkModelValidator);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,23 +1,22 @@
|
||||
using ApplicationLayer.Services.Users.Requests;
|
||||
using Domains.Users;
|
||||
|
||||
namespace ApplicationLayer.Services.Users
|
||||
namespace ApplicationLayer.Services.Users;
|
||||
|
||||
/// user accounts service
|
||||
public interface IUsersService
|
||||
{
|
||||
/// user accounts service
|
||||
public interface IUsersService
|
||||
{
|
||||
/// Returns all user accounts with role of approving authority
|
||||
/// <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
|
||||
/// <param name="request"> Request object with identifier of user and new authentication data</param>
|
||||
/// <param name="cancellationToken">Cancellation token</param>
|
||||
Task ChangeAccountAuthDataAsync(ChangeUserAuthDataRequest request, CancellationToken cancellationToken);
|
||||
/// Changes authentication data for an account
|
||||
/// <param name="request"> Request object with identifier of user and new authentication data</param>
|
||||
/// <param name="cancellationToken">Cancellation token</param>
|
||||
Task ChangeAccountAuthDataAsync(ChangeUserAuthDataRequest request, CancellationToken cancellationToken);
|
||||
|
||||
/// Removes user account
|
||||
/// <param name="userId">Identifier of account</param>
|
||||
/// <param name="cancellationToken">Cancellation token</param>
|
||||
Task RemoveUserAccount(Guid userId, CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
||||
/// Removes user account
|
||||
/// <param name="userId">Identifier of account</param>
|
||||
/// <param name="cancellationToken">Cancellation token</param>
|
||||
Task RemoveUserAccount(Guid userId, CancellationToken cancellationToken);
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
using ApplicationLayer.Services.AuthServices.Common;
|
||||
|
||||
namespace ApplicationLayer.Services.Users.Requests
|
||||
{
|
||||
public record ChangeUserAuthDataRequest(Guid UserId, AuthData NewAuthData);
|
||||
}
|
||||
namespace ApplicationLayer.Services.Users.Requests;
|
||||
|
||||
public record ChangeUserAuthDataRequest(Guid UserId, AuthData NewAuthData);
|
||||
@@ -3,17 +3,17 @@ using ApplicationLayer.Services.AuthServices.NeededServices;
|
||||
using ApplicationLayer.Services.Users.Requests;
|
||||
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);
|
||||
}
|
||||
|
||||
async Task IUsersService.ChangeAccountAuthDataAsync(ChangeUserAuthDataRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
async Task IUsersService.ChangeAccountAuthDataAsync(ChangeUserAuthDataRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var user = await users.GetByIdAsync(request.UserId, cancellationToken);
|
||||
|
||||
user.Email = request.NewAuthData.Email;
|
||||
@@ -23,12 +23,11 @@ namespace ApplicationLayer.Services.Users
|
||||
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);
|
||||
users.Remove(user);
|
||||
|
||||
await unitOfWork.SaveAsync(cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
using ApplicationLayer.GeneralExceptions;
|
||||
|
||||
namespace ApplicationLayer.Services.VisaApplications.Exceptions
|
||||
{
|
||||
public class ApplicationAlreadyProcessedException() : ApiException("This application already processed or closed by applicant.");
|
||||
}
|
||||
namespace ApplicationLayer.Services.VisaApplications.Exceptions;
|
||||
|
||||
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;
|
||||
|
||||
namespace ApplicationLayer.Services.VisaApplications.Models
|
||||
namespace ApplicationLayer.Services.VisaApplications.Models;
|
||||
|
||||
/// Model of <see cref="VisaApplication"/>
|
||||
public class VisaApplicationModelForApplicant
|
||||
{
|
||||
/// Model of <see cref="VisaApplication"/>
|
||||
public class VisaApplicationModelForApplicant
|
||||
{
|
||||
/// <inheritdoc cref="VisaApplication.Id"/>
|
||||
public Guid Id { get; set; }
|
||||
/// <inheritdoc cref="VisaApplication.Id"/>
|
||||
public Guid Id { get; set; }
|
||||
|
||||
/// <inheritdoc cref="VisaApplication.Status"/>
|
||||
public ApplicationStatus Status { get; set; }
|
||||
/// <inheritdoc cref="VisaApplication.Status"/>
|
||||
public ApplicationStatus Status { get; set; }
|
||||
|
||||
/// <inheritdoc cref="VisaApplication.ReentryPermit"/>
|
||||
public ReentryPermit? ReentryPermit { get; set; }
|
||||
/// <inheritdoc cref="VisaApplication.ReentryPermit"/>
|
||||
public ReentryPermit? ReentryPermit { get; set; }
|
||||
|
||||
/// <inheritdoc cref="VisaApplication.DestinationCountry"/>
|
||||
public string DestinationCountry { get; set; } = null!;
|
||||
/// <inheritdoc cref="VisaApplication.DestinationCountry"/>
|
||||
public string DestinationCountry { get; set; } = null!;
|
||||
|
||||
/// <inheritdoc cref="VisaApplication.PastVisas"/>
|
||||
public List<PastVisa> PastVisas { get; set; } = null!;
|
||||
/// <inheritdoc cref="VisaApplication.PastVisas"/>
|
||||
public List<PastVisa> PastVisas { get; set; } = null!;
|
||||
|
||||
/// <inheritdoc cref="VisaApplication.PermissionToDestCountry"/>
|
||||
public PermissionToDestCountry? PermissionToDestCountry { get; set; }
|
||||
/// <inheritdoc cref="VisaApplication.PermissionToDestCountry"/>
|
||||
public PermissionToDestCountry? PermissionToDestCountry { get; set; }
|
||||
|
||||
/// <inheritdoc cref="VisaApplication.PastVisits"/>
|
||||
public List<PastVisit> PastVisits { get; set; } = null!;
|
||||
/// <inheritdoc cref="VisaApplication.PastVisits"/>
|
||||
public List<PastVisit> PastVisits { get; set; } = null!;
|
||||
|
||||
/// <inheritdoc cref="VisaApplication.VisaCategory"/>
|
||||
public VisaCategory VisaCategory { get; set; }
|
||||
/// <inheritdoc cref="VisaApplication.VisaCategory"/>
|
||||
public VisaCategory VisaCategory { get; set; }
|
||||
|
||||
/// <inheritdoc cref="VisaApplication.ForGroup"/>
|
||||
public bool ForGroup { get; set; }
|
||||
/// <inheritdoc cref="VisaApplication.ForGroup"/>
|
||||
public bool ForGroup { get; set; }
|
||||
|
||||
/// <inheritdoc cref="VisaApplication.RequestedNumberOfEntries"/>
|
||||
public RequestedNumberOfEntries RequestedNumberOfEntries { get; set; }
|
||||
/// <inheritdoc cref="VisaApplication.RequestedNumberOfEntries"/>
|
||||
public RequestedNumberOfEntries RequestedNumberOfEntries { get; set; }
|
||||
|
||||
/// <inheritdoc cref="VisaApplication.RequestDate"/>
|
||||
public DateTime RequestDate { get; set; }
|
||||
/// <inheritdoc cref="VisaApplication.RequestDate"/>
|
||||
public DateTime RequestDate { get; set; }
|
||||
|
||||
/// <inheritdoc cref="VisaApplication.ValidDaysRequested"/>
|
||||
public int ValidDaysRequested { get; set; }
|
||||
}
|
||||
}
|
||||
/// <inheritdoc cref="VisaApplication.ValidDaysRequested"/>
|
||||
public int ValidDaysRequested { get; set; }
|
||||
}
|
||||
@@ -1,47 +1,46 @@
|
||||
using ApplicationLayer.Services.Applicants.Models;
|
||||
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
|
||||
public class VisaApplicationModelForAuthority
|
||||
{
|
||||
/// <inheritdoc cref="VisaApplication.Id"/>
|
||||
public Guid Id { get; set; }
|
||||
/// <inheritdoc cref="VisaApplication.Id"/>
|
||||
public Guid Id { get; set; }
|
||||
|
||||
/// Applicant of application
|
||||
public ApplicantModel Applicant { get; set; } = null!;
|
||||
/// Applicant of application
|
||||
public ApplicantModel Applicant { get; set; } = null!;
|
||||
|
||||
/// <inheritdoc cref="VisaApplication.Status"/>
|
||||
public ApplicationStatus Status { get; set; }
|
||||
/// <inheritdoc cref="VisaApplication.Status"/>
|
||||
public ApplicationStatus Status { get; set; }
|
||||
|
||||
/// <inheritdoc cref="VisaApplication.ReentryPermit"/>
|
||||
public ReentryPermit? ReentryPermit { get; set; }
|
||||
/// <inheritdoc cref="VisaApplication.ReentryPermit"/>
|
||||
public ReentryPermit? ReentryPermit { get; set; }
|
||||
|
||||
/// <inheritdoc cref="VisaApplication.DestinationCountry"/>
|
||||
public string DestinationCountry { get; set; } = null!;
|
||||
/// <inheritdoc cref="VisaApplication.DestinationCountry"/>
|
||||
public string DestinationCountry { get; set; } = null!;
|
||||
|
||||
/// <inheritdoc cref="VisaApplication.PastVisas"/>
|
||||
public List<PastVisa> PastVisas { get; set; } = null!;
|
||||
/// <inheritdoc cref="VisaApplication.PastVisas"/>
|
||||
public List<PastVisa> PastVisas { get; set; } = null!;
|
||||
|
||||
/// <inheritdoc cref="VisaApplication.PermissionToDestCountry"/>
|
||||
public PermissionToDestCountry? PermissionToDestCountry { get; set; }
|
||||
/// <inheritdoc cref="VisaApplication.PermissionToDestCountry"/>
|
||||
public PermissionToDestCountry? PermissionToDestCountry { get; set; }
|
||||
|
||||
public List<PastVisit> PastVisits { get; set; } = null!;
|
||||
public List<PastVisit> PastVisits { get; set; } = null!;
|
||||
|
||||
/// <inheritdoc cref="VisaApplication.VisaCategory"/>
|
||||
public VisaCategory VisaCategory { get; set; }
|
||||
/// <inheritdoc cref="VisaApplication.VisaCategory"/>
|
||||
public VisaCategory VisaCategory { get; set; }
|
||||
|
||||
/// <inheritdoc cref="VisaApplication.ForGroup"/>
|
||||
public bool ForGroup { get; set; }
|
||||
/// <inheritdoc cref="VisaApplication.ForGroup"/>
|
||||
public bool ForGroup { get; set; }
|
||||
|
||||
/// <inheritdoc cref="VisaApplication.RequestedNumberOfEntries"/>
|
||||
public RequestedNumberOfEntries RequestedNumberOfEntries { get; set; }
|
||||
/// <inheritdoc cref="VisaApplication.RequestedNumberOfEntries"/>
|
||||
public RequestedNumberOfEntries RequestedNumberOfEntries { get; set; }
|
||||
|
||||
/// <inheritdoc cref="VisaApplication.RequestDate"/>
|
||||
public DateTime RequestDate { get; set; }
|
||||
/// <inheritdoc cref="VisaApplication.RequestDate"/>
|
||||
public DateTime RequestDate { get; set; }
|
||||
|
||||
/// <inheritdoc cref="VisaApplication.ValidDaysRequested"/>
|
||||
public int ValidDaysRequested { get; set; }
|
||||
}
|
||||
}
|
||||
/// <inheritdoc cref="VisaApplication.ValidDaysRequested"/>
|
||||
public int ValidDaysRequested { get; set; }
|
||||
}
|
||||
@@ -2,12 +2,12 @@
|
||||
using Domains.VisaApplicationDomain;
|
||||
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)
|
||||
.NotEmpty()
|
||||
.WithMessage("Expiration date of past visa can not be empty")
|
||||
@@ -24,5 +24,4 @@ namespace ApplicationLayer.Services.VisaApplications.Requests.Validation
|
||||
.NotEmpty()
|
||||
.WithMessage("Name of past visa can not be empty");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,12 +3,12 @@ using Domains;
|
||||
using Domains.VisaApplicationDomain;
|
||||
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)
|
||||
.NotEmpty()
|
||||
.WithMessage("Start date of past visit can not be empty")
|
||||
@@ -27,5 +27,4 @@ namespace ApplicationLayer.Services.VisaApplications.Requests.Validation
|
||||
.MaximumLength(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 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)
|
||||
.NotEmpty()
|
||||
.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)
|
||||
.WithMessage($"Issuer of permission to destination Country length must be less than {ConfigurationConstraints.IssuerNameLength}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,12 +3,12 @@ using Domains;
|
||||
using Domains.VisaApplicationDomain;
|
||||
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)
|
||||
.NotEmpty()
|
||||
.WithMessage("Re-entry permit number can not be empty")
|
||||
@@ -21,5 +21,4 @@ namespace ApplicationLayer.Services.VisaApplications.Requests.Validation
|
||||
.GreaterThan(dateTimeProvider.Now())
|
||||
.WithMessage("Re-entry permit must not be expired");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,51 +4,50 @@ using Domains;
|
||||
using Domains.VisaApplicationDomain;
|
||||
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(
|
||||
IValidator<ReentryPermit?> reentryPermitValidator,
|
||||
IValidator<PastVisa> pastVisaValidator,
|
||||
IValidator<PermissionToDestCountry?> permissionToDestCountryValidator,
|
||||
IValidator<PastVisit> pastVisitValidator,
|
||||
IApplicantsRepository applicants,
|
||||
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.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)
|
||||
.NotEmpty()
|
||||
.WithMessage("Destination country can not be empty");
|
||||
RuleFor(r => r.DestinationCountry)
|
||||
.NotEmpty()
|
||||
.WithMessage("Destination country can not be empty");
|
||||
|
||||
RuleFor(r => r.VisaCategory)
|
||||
.IsInEnum();
|
||||
RuleFor(r => r.VisaCategory)
|
||||
.IsInEnum();
|
||||
|
||||
RuleFor(r => r.RequestedNumberOfEntries)
|
||||
.IsInEnum();
|
||||
RuleFor(r => r.RequestedNumberOfEntries)
|
||||
.IsInEnum();
|
||||
|
||||
RuleFor(r => r.ValidDaysRequested)
|
||||
.GreaterThan(0)
|
||||
.WithMessage($"Valid days requested should be positive number and less than {ConfigurationConstraints.MaxValidDays}")
|
||||
.LessThanOrEqualTo(ConfigurationConstraints.MaxValidDays)
|
||||
.WithMessage($"Valid days requested must be less than or equal to {ConfigurationConstraints.MaxValidDays}");
|
||||
RuleFor(r => r.ValidDaysRequested)
|
||||
.GreaterThan(0)
|
||||
.WithMessage($"Valid days requested should be positive number and less than {ConfigurationConstraints.MaxValidDays}")
|
||||
.LessThanOrEqualTo(ConfigurationConstraints.MaxValidDays)
|
||||
.WithMessage($"Valid days requested must be less than or equal to {ConfigurationConstraints.MaxValidDays}");
|
||||
|
||||
RuleForEach(r => r.PastVisas)
|
||||
.SetValidator(pastVisaValidator);
|
||||
RuleForEach(r => r.PastVisas)
|
||||
.SetValidator(pastVisaValidator);
|
||||
|
||||
When(r => r.VisaCategory == VisaCategory.Transit,
|
||||
() =>
|
||||
RuleFor(r => r.PermissionToDestCountry)
|
||||
.SetValidator(permissionToDestCountryValidator));
|
||||
When(r => r.VisaCategory == VisaCategory.Transit,
|
||||
() =>
|
||||
RuleFor(r => r.PermissionToDestCountry)
|
||||
.SetValidator(permissionToDestCountryValidator));
|
||||
|
||||
RuleForEach(r => r.PastVisits)
|
||||
.SetValidator(pastVisitValidator);
|
||||
}
|
||||
RuleForEach(r => r.PastVisits)
|
||||
.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 CitizenshipLength = 30;
|
||||
public const int ReentryPermitNumberLength = 25;
|
||||
public const int IssuerNameLength = 200;
|
||||
public const int VisaNameLength = 70;
|
||||
public const int StreetNameLength = 100;
|
||||
public const int PlaceOfWorkNameLength = 200;
|
||||
public const int NameLength = 50;
|
||||
public const int BuildingNumberLength = 10;
|
||||
public const int PassportNumberLength = 20;
|
||||
public const int PhoneNumberLength = 13;
|
||||
public const int PhoneNumberMinLength = 11;
|
||||
public const int EmailLength = 254;
|
||||
public const int PasswordLength = 50;
|
||||
public const int ApplicantMinAge = 14;
|
||||
public const int JobTitleLength = 50;
|
||||
public const int MaxValidDays = 90;
|
||||
}
|
||||
}
|
||||
public const int CityNameLength = 70;
|
||||
public const int CountryNameLength = 70;
|
||||
public const int CitizenshipLength = 30;
|
||||
public const int ReentryPermitNumberLength = 25;
|
||||
public const int IssuerNameLength = 200;
|
||||
public const int VisaNameLength = 70;
|
||||
public const int StreetNameLength = 100;
|
||||
public const int PlaceOfWorkNameLength = 200;
|
||||
public const int NameLength = 50;
|
||||
public const int BuildingNumberLength = 10;
|
||||
public const int PassportNumberLength = 20;
|
||||
public const int PhoneNumberLength = 13;
|
||||
public const int PhoneNumberMinLength = 11;
|
||||
public const int EmailLength = 254;
|
||||
public const int PasswordLength = 50;
|
||||
public const int ApplicantMinAge = 14;
|
||||
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"/>
|
||||
public enum Role
|
||||
{
|
||||
/// Requests visa applications
|
||||
Applicant,
|
||||
/// Approves or declines applications
|
||||
ApprovingAuthority,
|
||||
/// Manages approving authorities
|
||||
Admin
|
||||
}
|
||||
}
|
||||
/// Requests visa applications
|
||||
Applicant,
|
||||
/// Approves or declines applications
|
||||
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,
|
||||
Approved,
|
||||
Rejected,
|
||||
/// Closed by applicant
|
||||
Closed
|
||||
}
|
||||
}
|
||||
/// Waits for approve
|
||||
Pending,
|
||||
Approved,
|
||||
Rejected,
|
||||
/// Closed by applicant
|
||||
Closed
|
||||
}
|
||||
@@ -3,12 +3,12 @@ using ApplicationLayer.InfrastructureServicesInterfaces;
|
||||
using ApplicationLayer.Services.AuthServices.NeededServices;
|
||||
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<ITokenGenerator, TokenGenerator>(provider =>
|
||||
{
|
||||
@@ -20,5 +20,4 @@ namespace Infrastructure.Auth
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,27 +4,26 @@ using ApplicationLayer.InfrastructureServicesInterfaces;
|
||||
using ApplicationLayer.Services.AuthServices.NeededServices;
|
||||
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)
|
||||
: ITokenGenerator
|
||||
public string CreateToken(User user)
|
||||
{
|
||||
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(
|
||||
issuer: options.Issuer,
|
||||
audience: options.Audience,
|
||||
expires: dateTimeProvider.Now().Add(options.ValidTime),
|
||||
signingCredentials: options.Credentials,
|
||||
claims: claims);
|
||||
var token = new JwtSecurityToken(
|
||||
issuer: options.Issuer,
|
||||
audience: options.Audience,
|
||||
expires: dateTimeProvider.Now().Add(options.ValidTime),
|
||||
signingCredentials: options.Credentials,
|
||||
claims: claims);
|
||||
|
||||
return tokenHandler.WriteToken(token);
|
||||
}
|
||||
return tokenHandler.WriteToken(token);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
|
||||
namespace Infrastructure.Auth
|
||||
{
|
||||
public record TokenGeneratorOptions(string Issuer, string Audience, TimeSpan ValidTime, SigningCredentials Credentials);
|
||||
}
|
||||
namespace Infrastructure.Auth;
|
||||
|
||||
public record TokenGeneratorOptions(string Issuer, string Audience, TimeSpan ValidTime, SigningCredentials Credentials);
|
||||
@@ -3,12 +3,12 @@ using ApplicationLayer.Services.AuthServices.Requests;
|
||||
using AutoMapper;
|
||||
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<RegisterApplicantRequest, Applicant>(MemberList.Destination)
|
||||
@@ -16,5 +16,4 @@ namespace Infrastructure.Automapper.Profiles
|
||||
.ForMember(a => a.Name,
|
||||
opts => opts.MapFrom(r => r.ApplicantName));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,15 +2,14 @@
|
||||
using AutoMapper;
|
||||
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)
|
||||
.ForMember(p => p.Id,
|
||||
opts => opts.UseDestinationValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,15 +2,14 @@
|
||||
using AutoMapper;
|
||||
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)
|
||||
.ForMember(u => u.Role,
|
||||
opts => opts.Ignore());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,12 +3,12 @@ using ApplicationLayer.Services.VisaApplications.Requests;
|
||||
using AutoMapper;
|
||||
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, VisaApplicationModelForAuthority>(MemberList.Destination)
|
||||
@@ -21,5 +21,4 @@ namespace Infrastructure.Automapper.Profiles
|
||||
.ForMember(va => va.ApplicantId,
|
||||
opts => opts.Ignore());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,9 @@
|
||||
using ApplicationLayer.InfrastructureServicesInterfaces;
|
||||
|
||||
namespace Infrastructure.Common
|
||||
namespace Infrastructure.Common;
|
||||
|
||||
/// Implements <see cref="IDateTimeProvider"/>
|
||||
public class DateTimeProvider : IDateTimeProvider
|
||||
{
|
||||
/// Implements <see cref="IDateTimeProvider"/>
|
||||
public class DateTimeProvider : IDateTimeProvider
|
||||
{
|
||||
DateTime IDateTimeProvider.Now() => DateTime.Now;
|
||||
}
|
||||
}
|
||||
DateTime IDateTimeProvider.Now() => DateTime.Now;
|
||||
}
|
||||
@@ -2,12 +2,12 @@
|
||||
using ApplicationLayer.InfrastructureServicesInterfaces;
|
||||
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);
|
||||
if (claim is null)
|
||||
{
|
||||
@@ -15,5 +15,4 @@ namespace Infrastructure.Common
|
||||
}
|
||||
return Guid.Parse(claim.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
using ApplicationLayer.Services.GeneralExceptions;
|
||||
|
||||
namespace Infrastructure.Database.Applicants.Repositories.Exceptions
|
||||
{
|
||||
public class ApplicantNotFoundByUserIdException() : EntityNotFoundException("Applicant not found.");
|
||||
}
|
||||
namespace Infrastructure.Database.Applicants.Repositories.Exceptions;
|
||||
|
||||
public class ApplicantNotFoundByUserIdException() : EntityNotFoundException("Applicant not found.");
|
||||
|
||||
@@ -3,12 +3,12 @@ using Domains.Users;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
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)
|
||||
.IsUnicode(false)
|
||||
.HasMaxLength(ConfigurationConstraints.EmailLength);
|
||||
@@ -19,5 +19,4 @@ namespace Infrastructure.Database.Users.Configuration
|
||||
.IsUnicode(false)
|
||||
.HasMaxLength(ConfigurationConstraints.PasswordLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,20 +3,19 @@ using Domains.Users;
|
||||
using Infrastructure.Database.Generic;
|
||||
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"/>
|
||||
public class UsersRepository(IGenericReader reader, IGenericWriter writer)
|
||||
: GenericRepository<User>(reader, writer), IUsersRepository
|
||||
async Task<User?> IUsersRepository.FindByEmailAsync(string email, CancellationToken cancellationToken)
|
||||
{
|
||||
async Task<User?> IUsersRepository.FindByEmailAsync(string email, CancellationToken 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,15 +2,14 @@
|
||||
using Domains.VisaApplicationDomain;
|
||||
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)
|
||||
.IsUnicode(false)
|
||||
.HasMaxLength(ConfigurationConstraints.CountryNameLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
using ApplicationLayer.Services.GeneralExceptions;
|
||||
|
||||
namespace Infrastructure.Database.VisaApplications.Repositories.Exceptions
|
||||
{
|
||||
public class ApplicationNotFoundByApplicantAndApplicationIdException(Guid applicationId)
|
||||
: EntityNotFoundException($"Application with id {applicationId} not found for authenticated user");
|
||||
}
|
||||
namespace Infrastructure.Database.VisaApplications.Repositories.Exceptions;
|
||||
|
||||
public class ApplicationNotFoundByApplicantAndApplicationIdException(Guid applicationId)
|
||||
: EntityNotFoundException($"Application with id {applicationId} not found for authenticated user");
|
||||
@@ -2,13 +2,13 @@
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Swashbuckle.AspNetCore.SwaggerGen;
|
||||
|
||||
namespace SchengenVisaApi.Common
|
||||
namespace SchengenVisaApi.Common;
|
||||
|
||||
/// Adds auth for swagger
|
||||
public class ConfigureSwaggerOptions : IConfigureOptions<SwaggerGenOptions>
|
||||
{
|
||||
/// Adds auth for swagger
|
||||
public class ConfigureSwaggerOptions : IConfigureOptions<SwaggerGenOptions>
|
||||
void IConfigureOptions<SwaggerGenOptions>.Configure(SwaggerGenOptions options)
|
||||
{
|
||||
void IConfigureOptions<SwaggerGenOptions>.Configure(SwaggerGenOptions options)
|
||||
{
|
||||
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
|
||||
{
|
||||
In = ParameterLocation.Header,
|
||||
@@ -34,5 +34,4 @@ namespace SchengenVisaApi.Common
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,9 @@
|
||||
namespace SchengenVisaApi.Common
|
||||
{
|
||||
namespace SchengenVisaApi.Common;
|
||||
#pragma warning disable CS1591
|
||||
public static class PolicyConstants
|
||||
{
|
||||
public const string AdminPolicy = "AdminPolicy";
|
||||
public const string ApplicantPolicy = "ApplicantPolicy";
|
||||
public const string ApprovingAuthorityPolicy = "ApprovingAuthorityPolicy";
|
||||
}
|
||||
#pragma warning enable CS1591
|
||||
|
||||
public static class PolicyConstants
|
||||
{
|
||||
public const string AdminPolicy = "AdminPolicy";
|
||||
public const string ApplicantPolicy = "ApplicantPolicy";
|
||||
public const string ApprovingAuthorityPolicy = "ApprovingAuthorityPolicy";
|
||||
}
|
||||
#pragma warning enable CS1591
|
||||
@@ -10,106 +10,105 @@ using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
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>
|
||||
[ApiController]
|
||||
[Route("users")]
|
||||
public class UsersController(
|
||||
IRegisterService registerService,
|
||||
ILoginService loginService,
|
||||
IUsersService usersService,
|
||||
IValidator<RegisterApplicantRequest> registerApplicantRequestValidator,
|
||||
IValidator<AuthData> authDataValidator) : ControllerBase
|
||||
/// <summary> Adds applicant with user account to DB </summary>
|
||||
[HttpPost]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status409Conflict)]
|
||||
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||
[Route("register")]
|
||||
public async Task<IActionResult> Register(RegisterApplicantRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
/// <summary> Adds applicant with user account to DB </summary>
|
||||
[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 registerApplicantRequestValidator.ValidateAndThrowAsync(request, cancellationToken);
|
||||
|
||||
await registerService.RegisterApplicant(request, 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();
|
||||
}
|
||||
await registerService.RegisterApplicant(request, 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.Filters;
|
||||
|
||||
namespace SchengenVisaApi.ExceptionFilters
|
||||
namespace SchengenVisaApi.ExceptionFilters;
|
||||
|
||||
/// Handles <see cref="ApiException"/>
|
||||
public class GlobalExceptionsFilter : IAsyncExceptionFilter
|
||||
{
|
||||
/// Handles <see cref="ApiException"/>
|
||||
public class GlobalExceptionsFilter : IAsyncExceptionFilter
|
||||
/// <inheritdoc cref="IExceptionFilter.OnException"/>
|
||||
public async Task OnExceptionAsync(ExceptionContext context)
|
||||
{
|
||||
/// <inheritdoc cref="IExceptionFilter.OnException"/>
|
||||
public async Task OnExceptionAsync(ExceptionContext context)
|
||||
var exception = context.Exception;
|
||||
var problemDetails = new ProblemDetails();
|
||||
|
||||
switch (exception)
|
||||
{
|
||||
var exception = context.Exception;
|
||||
var problemDetails = new ProblemDetails();
|
||||
case ValidationException validationException:
|
||||
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)
|
||||
{
|
||||
case ValidationException validationException:
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user