Compare commits
5 Commits
91805bc9ad
...
2d7d23d26b
Author | SHA1 | Date | |
---|---|---|---|
2d7d23d26b | |||
fafb665cd2 | |||
4ae17c5a91 | |||
57264b384c | |||
a97b95a704 |
1
.github/workflows/ci-cd.yml
vendored
1
.github/workflows/ci-cd.yml
vendored
@ -25,7 +25,6 @@ jobs:
|
||||
cache: true
|
||||
cache-dependency-path: |
|
||||
src/Application/packages.lock.json
|
||||
src/Identity/packages.lock.json
|
||||
src/Infrastructure/packages.lock.json
|
||||
src/Persistence/packages.lock.json
|
||||
src/Configuration/packages.lock.json
|
||||
|
@ -13,8 +13,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Infrastructure", "src\Infra
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HttpApi", "src\HttpApi\HttpApi.csproj", "{4431B3CB-A5F2-447A-8BC7-9DC3DA9E6A6D}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Identity", "src\Identity\Identity.csproj", "{AD3CC01F-0331-44DC-B58E-CCE6ADCB56B6}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Configuration", "src\Configuration\Configuration.csproj", "{1DCFA4EE-A545-42FE-A3BC-A606D2961298}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Application.IntegrationTests", "tst\Application.IntegrationTests\Application.IntegrationTests.csproj", "{B52B8651-10B8-488D-8ACF-9C4499F8A723}"
|
||||
@ -48,10 +46,6 @@ Global
|
||||
{4431B3CB-A5F2-447A-8BC7-9DC3DA9E6A6D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4431B3CB-A5F2-447A-8BC7-9DC3DA9E6A6D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4431B3CB-A5F2-447A-8BC7-9DC3DA9E6A6D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{AD3CC01F-0331-44DC-B58E-CCE6ADCB56B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AD3CC01F-0331-44DC-B58E-CCE6ADCB56B6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AD3CC01F-0331-44DC-B58E-CCE6ADCB56B6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AD3CC01F-0331-44DC-B58E-CCE6ADCB56B6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1DCFA4EE-A545-42FE-A3BC-A606D2961298}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1DCFA4EE-A545-42FE-A3BC-A606D2961298}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1DCFA4EE-A545-42FE-A3BC-A606D2961298}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
|
@ -1,6 +1,6 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Authorization;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
using cuqmbr.TravelGuide.Application.Common.Models;
|
||||
using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using cuqmbr.TravelGuide.Domain.Enums;
|
||||
using MediatR.Behaviors.Authorization;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Addresses.Commands.AddAddress;
|
||||
|
@ -1,5 +1,5 @@
|
||||
using MediatR;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Persistence;
|
||||
using cuqmbr.TravelGuide.Application.Common.Persistence;
|
||||
using cuqmbr.TravelGuide.Domain.Entities;
|
||||
using AutoMapper;
|
||||
using cuqmbr.TravelGuide.Application.Common.Exceptions;
|
||||
|
@ -1,4 +1,4 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using cuqmbr.TravelGuide.Domain.Enums;
|
||||
using FluentValidation;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
@ -1,6 +1,6 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Authorization;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
using cuqmbr.TravelGuide.Application.Common.Models;
|
||||
using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using cuqmbr.TravelGuide.Domain.Enums;
|
||||
using MediatR.Behaviors.Authorization;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Addresses.Commands.DeleteAddress;
|
||||
|
@ -1,5 +1,5 @@
|
||||
using MediatR;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Persistence;
|
||||
using cuqmbr.TravelGuide.Application.Common.Persistence;
|
||||
using cuqmbr.TravelGuide.Application.Common.Exceptions;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Addresses.Commands.DeleteAddress;
|
||||
|
@ -1,6 +1,6 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Authorization;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
using cuqmbr.TravelGuide.Application.Common.Models;
|
||||
using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using cuqmbr.TravelGuide.Domain.Enums;
|
||||
using MediatR.Behaviors.Authorization;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Addresses.Commands.UpdateAddress;
|
||||
|
@ -1,5 +1,5 @@
|
||||
using MediatR;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Persistence;
|
||||
using cuqmbr.TravelGuide.Application.Common.Persistence;
|
||||
using AutoMapper;
|
||||
using cuqmbr.TravelGuide.Application.Common.Exceptions;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using FluentValidation;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Authorization;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
using cuqmbr.TravelGuide.Application.Common.Models;
|
||||
using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using cuqmbr.TravelGuide.Domain.Enums;
|
||||
using MediatR.Behaviors.Authorization;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Addresses.Queries.GetAddress;
|
||||
|
@ -1,5 +1,5 @@
|
||||
using MediatR;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Persistence;
|
||||
using cuqmbr.TravelGuide.Application.Common.Persistence;
|
||||
using cuqmbr.TravelGuide.Application.Common.Exceptions;
|
||||
using AutoMapper;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Authorization;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
using cuqmbr.TravelGuide.Application.Common.Models;
|
||||
using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using cuqmbr.TravelGuide.Domain.Enums;
|
||||
using MediatR.Behaviors.Authorization;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Addresses.Queries.GetAddressesPage;
|
||||
|
@ -1,5 +1,5 @@
|
||||
using MediatR;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Persistence;
|
||||
using cuqmbr.TravelGuide.Application.Common.Persistence;
|
||||
using AutoMapper;
|
||||
using cuqmbr.TravelGuide.Application.Common.Models;
|
||||
using cuqmbr.TravelGuide.Application.Common.Extensions;
|
||||
|
@ -1,4 +1,4 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using FluentValidation;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Authorization;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
using cuqmbr.TravelGuide.Application.Common.Models;
|
||||
using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using cuqmbr.TravelGuide.Domain.Enums;
|
||||
using MediatR.Behaviors.Authorization;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Aircrafts.Commands.AddAircraft;
|
||||
|
@ -1,5 +1,5 @@
|
||||
using MediatR;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Persistence;
|
||||
using cuqmbr.TravelGuide.Application.Common.Persistence;
|
||||
using cuqmbr.TravelGuide.Domain.Entities;
|
||||
using AutoMapper;
|
||||
using cuqmbr.TravelGuide.Application.Common.Exceptions;
|
||||
|
@ -1,4 +1,4 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using FluentValidation;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Authorization;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
using cuqmbr.TravelGuide.Application.Common.Models;
|
||||
using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using cuqmbr.TravelGuide.Domain.Enums;
|
||||
using MediatR.Behaviors.Authorization;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Aircrafts.Commands.DeleteAircraft;
|
||||
|
@ -1,5 +1,5 @@
|
||||
using MediatR;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Persistence;
|
||||
using cuqmbr.TravelGuide.Application.Common.Persistence;
|
||||
using cuqmbr.TravelGuide.Application.Common.Exceptions;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Aircrafts.Commands.DeleteAircraft;
|
||||
|
@ -1,6 +1,6 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Authorization;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
using cuqmbr.TravelGuide.Application.Common.Models;
|
||||
using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using cuqmbr.TravelGuide.Domain.Enums;
|
||||
using MediatR.Behaviors.Authorization;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Aircrafts.Commands.UpdateAircraft;
|
||||
|
@ -1,5 +1,5 @@
|
||||
using MediatR;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Persistence;
|
||||
using cuqmbr.TravelGuide.Application.Common.Persistence;
|
||||
using AutoMapper;
|
||||
using cuqmbr.TravelGuide.Application.Common.Exceptions;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using FluentValidation;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Authorization;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
using cuqmbr.TravelGuide.Application.Common.Models;
|
||||
using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using cuqmbr.TravelGuide.Domain.Enums;
|
||||
using MediatR.Behaviors.Authorization;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Aircrafts.Queries.GetAircraft;
|
||||
|
@ -1,5 +1,5 @@
|
||||
using MediatR;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Persistence;
|
||||
using cuqmbr.TravelGuide.Application.Common.Persistence;
|
||||
using cuqmbr.TravelGuide.Application.Common.Exceptions;
|
||||
using AutoMapper;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Authorization;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
using cuqmbr.TravelGuide.Application.Common.Models;
|
||||
using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using cuqmbr.TravelGuide.Domain.Enums;
|
||||
using MediatR.Behaviors.Authorization;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Aircrafts.Queries.GetAircraftsPage;
|
||||
|
@ -1,5 +1,5 @@
|
||||
using MediatR;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Persistence;
|
||||
using cuqmbr.TravelGuide.Application.Common.Persistence;
|
||||
using AutoMapper;
|
||||
using cuqmbr.TravelGuide.Application.Common.Models;
|
||||
using cuqmbr.TravelGuide.Application.Common.Extensions;
|
||||
|
@ -1,4 +1,4 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using FluentValidation;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
|
@ -16,7 +16,10 @@
|
||||
<PackageReference Include="FluentValidation" Version="11.11.0" />
|
||||
<PackageReference Include="MediatR" Version="12.4.1" />
|
||||
<PackageReference Include="MediatR.Behaviors.Authorization" Version="12.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.5" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.11.0" />
|
||||
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="8.11.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="QuikGraph" Version="2.5.0" />
|
||||
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.6.2" />
|
||||
|
@ -4,6 +4,8 @@ namespace cuqmbr.TravelGuide.Application.Authenticaion.Commands.Register;
|
||||
|
||||
public record RegisterCommand : IRequest
|
||||
{
|
||||
public string Username { get; set; }
|
||||
|
||||
public string Email { get; set; }
|
||||
|
||||
public string Password { get; set; }
|
||||
|
@ -0,0 +1,13 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Authorization;
|
||||
using MediatR.Behaviors.Authorization;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Authenticaion.Commands.Register;
|
||||
|
||||
public class RegisterCommandAuthorizer :
|
||||
AbstractRequestAuthorizer<RegisterCommand>
|
||||
{
|
||||
public override void BuildPolicy(RegisterCommand request)
|
||||
{
|
||||
UseRequirement(new AllowAllRequirement());
|
||||
}
|
||||
}
|
@ -1,21 +1,83 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using cuqmbr.TravelGuide.Application.Common.Exceptions;
|
||||
using cuqmbr.TravelGuide.Application.Common.Persistence;
|
||||
using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using cuqmbr.TravelGuide.Domain.Entities;
|
||||
using cuqmbr.TravelGuide.Domain.Enums;
|
||||
using MediatR;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Authenticaion.Commands.Register;
|
||||
|
||||
public class RegisterCommandHandler : IRequestHandler<RegisterCommand>
|
||||
{
|
||||
private readonly AuthenticationService _authenticationService;
|
||||
private readonly IReadOnlyCollection<IdentityRole> DefaultRoles =
|
||||
new IdentityRole[] { IdentityRole.User };
|
||||
|
||||
public RegisterCommandHandler(AuthenticationService authenticationService)
|
||||
private readonly UnitOfWork _unitOfWork;
|
||||
private readonly PasswordHasherService _passwordHasher;
|
||||
|
||||
public RegisterCommandHandler(UnitOfWork unitOfWork,
|
||||
PasswordHasherService passwordHasher)
|
||||
{
|
||||
_authenticationService = authenticationService;
|
||||
_unitOfWork = unitOfWork;
|
||||
_passwordHasher = passwordHasher;
|
||||
}
|
||||
|
||||
public async Task Handle(
|
||||
RegisterCommand request, CancellationToken cancellationToken)
|
||||
public async Task Handle(RegisterCommand request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
await _authenticationService.RegisterAsync(
|
||||
request.Email, request.Password, cancellationToken);
|
||||
var datastoreAccount = await _unitOfWork.AccountRepository
|
||||
.GetOneAsync(
|
||||
e =>
|
||||
e.Email == request.Email ||
|
||||
e.Username == request.Username,
|
||||
cancellationToken);
|
||||
|
||||
if (datastoreAccount != null)
|
||||
{
|
||||
throw new RegistrationException(
|
||||
"User with given email or username already registered.");
|
||||
}
|
||||
|
||||
|
||||
var defaultRoleIds = (await _unitOfWork.RoleRepository
|
||||
.GetPageAsync(
|
||||
r => DefaultRoles.Contains(r.Value),
|
||||
1, DefaultRoles.Count, cancellationToken))
|
||||
.Items
|
||||
.Select(r => r.Id);
|
||||
|
||||
|
||||
var password = Encoding.UTF8.GetBytes(request.Password);
|
||||
|
||||
var salt = RandomNumberGenerator.GetBytes(128 / 8);
|
||||
var hash = await _passwordHasher
|
||||
.HashAsync(password, salt, cancellationToken);
|
||||
|
||||
var saltBase64 = Convert.ToBase64String(salt);
|
||||
var hashBase64 = Convert.ToBase64String(hash);
|
||||
|
||||
|
||||
var newAccount = new Account
|
||||
{
|
||||
Username = request.Username,
|
||||
Email = request.Email,
|
||||
PasswordHash = hashBase64,
|
||||
PasswordSalt = saltBase64,
|
||||
AccountRoles = defaultRoleIds.Select(id =>
|
||||
new AccountRole()
|
||||
{
|
||||
RoleId = id
|
||||
})
|
||||
.ToArray()
|
||||
};
|
||||
|
||||
|
||||
await _unitOfWork.AccountRepository
|
||||
.AddOneAsync(newAccount, cancellationToken);
|
||||
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
_unitOfWork.Dispose();
|
||||
}
|
||||
}
|
||||
|
@ -1,31 +1,54 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.FluentValidation;
|
||||
using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using FluentValidation;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Authenticaion.Commands.Register;
|
||||
|
||||
public class RegisterCommandValidator : AbstractValidator<RegisterCommand>
|
||||
{
|
||||
public RegisterCommandValidator()
|
||||
public RegisterCommandValidator(
|
||||
IStringLocalizer localizer,
|
||||
SessionCultureService cultureService)
|
||||
{
|
||||
RuleFor(v => v.Username)
|
||||
.NotEmpty()
|
||||
.WithMessage(localizer["FluentValidation.NotEmpty"])
|
||||
.MinimumLength(1)
|
||||
.WithMessage(
|
||||
String.Format(
|
||||
cultureService.Culture,
|
||||
localizer["FluentValidation.MinimumLength"],
|
||||
1))
|
||||
.MaximumLength(32)
|
||||
.WithMessage(
|
||||
String.Format(
|
||||
cultureService.Culture,
|
||||
localizer["FluentValidation.MaximumLength"],
|
||||
32))
|
||||
.IsUsername()
|
||||
.WithMessage(localizer["FluentValidation.IsUsername"]);
|
||||
|
||||
RuleFor(v => v.Email)
|
||||
.NotEmpty()
|
||||
.WithMessage("Email address is required.")
|
||||
.Matches(@"\b[\w\.-]+@[\w\.-]+\.\w{2,4}\b")
|
||||
.WithMessage("Email address is invalid.");
|
||||
.WithMessage(localizer["FluentValidation.NotEmpty"])
|
||||
.IsEmail()
|
||||
.WithMessage(localizer["FluentValidation.IsEmail"]);
|
||||
|
||||
RuleFor(v => v.Password)
|
||||
.NotEmpty()
|
||||
.WithMessage("Password is required.")
|
||||
.WithMessage(localizer["FluentValidation.NotEmpty"])
|
||||
.MinimumLength(8)
|
||||
.WithMessage("Password must be at least 8 characters long.")
|
||||
.MaximumLength(64)
|
||||
.WithMessage("Password must be at most 64 characters long.")
|
||||
.Matches(@"(?=.*[A-Z]).*")
|
||||
.WithMessage("Password must contain at least one uppercase letter.")
|
||||
.Matches(@"(?=.*[a-z]).*")
|
||||
.WithMessage("Password must contain at least one lowercase letter.")
|
||||
.Matches(@"(?=.*[\d]).*")
|
||||
.WithMessage("Password must contain at least one digit.")
|
||||
.Matches(@"(?=.*[!@#$%^&*()]).*")
|
||||
.WithMessage("Password must contain at least one of the following special charactters: !@#$%^&*().");
|
||||
.WithMessage(
|
||||
String.Format(
|
||||
cultureService.Culture,
|
||||
localizer["FluentValidation.MinimumLength"],
|
||||
8))
|
||||
.MaximumLength(256)
|
||||
.WithMessage(
|
||||
String.Format(
|
||||
cultureService.Culture,
|
||||
localizer["FluentValidation.MaximumLength"],
|
||||
256));
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Authorization;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
// using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using MediatR.Behaviors.Authorization;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Authenticaion.Commands.RenewAccessToken;
|
||||
@ -7,18 +7,19 @@ namespace cuqmbr.TravelGuide.Application.Authenticaion.Commands.RenewAccessToken
|
||||
public class RenewAccessTokenCommandAuthorizer :
|
||||
AbstractRequestAuthorizer<RenewAccessTokenCommand>
|
||||
{
|
||||
private readonly SessionUserService _sessionUserService;
|
||||
|
||||
public RenewAccessTokenCommandAuthorizer(SessionUserService currentUserService)
|
||||
{
|
||||
_sessionUserService = currentUserService;
|
||||
}
|
||||
// private readonly SessionUserService _sessionUserService;
|
||||
//
|
||||
// public RenewAccessTokenCommandAuthorizer(SessionUserService currentUserService)
|
||||
// {
|
||||
// _sessionUserService = currentUserService;
|
||||
// }
|
||||
|
||||
public override void BuildPolicy(RenewAccessTokenCommand request)
|
||||
{
|
||||
UseRequirement(new MustBeAuthenticatedRequirement
|
||||
{
|
||||
IsAuthenticated = _sessionUserService.IsAuthenticated
|
||||
});
|
||||
UseRequirement(new AllowAllRequirement());
|
||||
// UseRequirement(new MustBeAuthenticatedRequirement
|
||||
// {
|
||||
// IsAuthenticated = _sessionUserService.IsAuthenticated
|
||||
// });
|
||||
}
|
||||
}
|
||||
|
@ -1,22 +1,95 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Security.Claims;
|
||||
using System.Text;
|
||||
using cuqmbr.TravelGuide.Application.Common.Exceptions;
|
||||
using cuqmbr.TravelGuide.Application.Common.Persistence;
|
||||
using cuqmbr.TravelGuide.Domain.Entities;
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Authenticaion.Commands.RenewAccessToken;
|
||||
|
||||
public class RenewAccessTokenCommandHandler :
|
||||
IRequestHandler<RenewAccessTokenCommand, TokensModel>
|
||||
{
|
||||
private readonly AuthenticationService _authenticationService;
|
||||
private readonly UnitOfWork _unitOfWork;
|
||||
private readonly JsonWebTokenConfigurationOptions _jwtConfiguration;
|
||||
|
||||
public RenewAccessTokenCommandHandler(AuthenticationService authenticationService)
|
||||
public RenewAccessTokenCommandHandler(UnitOfWork unitOfWork,
|
||||
IOptions<ConfigurationOptions> configurationOptions)
|
||||
{
|
||||
_authenticationService = authenticationService;
|
||||
_unitOfWork = unitOfWork;
|
||||
_jwtConfiguration = configurationOptions.Value.JsonWebToken;
|
||||
}
|
||||
|
||||
public async Task<TokensModel> Handle(
|
||||
RenewAccessTokenCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
return await _authenticationService.RenewAccessTokenAsync(
|
||||
request.RefreshToken, cancellationToken);
|
||||
var refreshToken = (await _unitOfWork.RefreshTokenRepository
|
||||
.GetOneAsync(e => e.Value == request.RefreshToken,
|
||||
cancellationToken));
|
||||
|
||||
if (refreshToken == null)
|
||||
{
|
||||
throw new AuthenticationException($"Refresh token was not found.");
|
||||
}
|
||||
|
||||
if (!refreshToken.IsActive)
|
||||
{
|
||||
throw new AuthenticationException("Refresh token is inactive.");
|
||||
}
|
||||
|
||||
var account = await _unitOfWork.AccountRepository.GetOneAsync(
|
||||
a => a.RefreshTokens.Contains(refreshToken),
|
||||
a => a.AccountRoles, cancellationToken);
|
||||
|
||||
var jwtSecurityToken = await CreateJwtAsync(account, cancellationToken);
|
||||
var accessToken = new JwtSecurityTokenHandler().WriteToken(jwtSecurityToken);
|
||||
|
||||
return new TokensModel(accessToken, refreshToken.Value);
|
||||
}
|
||||
|
||||
private async Task<JwtSecurityToken> CreateJwtAsync(
|
||||
Account account, CancellationToken cancellationToken)
|
||||
{
|
||||
var roleIds = account.AccountRoles.Select(ar => ar.RoleId);
|
||||
|
||||
var roles = (await _unitOfWork.RoleRepository
|
||||
.GetPageAsync(
|
||||
r => roleIds.Contains(r.Id),
|
||||
1, roleIds.Count(), cancellationToken))
|
||||
.Items.Select(r => r.Value);
|
||||
|
||||
var roleClaims = new List<Claim>();
|
||||
foreach (var role in roles)
|
||||
{
|
||||
roleClaims.Add(new Claim("roles", role.Name));
|
||||
}
|
||||
|
||||
var claims = new List<Claim>()
|
||||
{
|
||||
new Claim(JwtRegisteredClaimNames.Sub, account.Guid.ToString()),
|
||||
new Claim(JwtRegisteredClaimNames.Nickname, account.Username),
|
||||
new Claim(JwtRegisteredClaimNames.Email, account.Email)
|
||||
}
|
||||
.Union(roleClaims);
|
||||
|
||||
var expirationDateTimeUtc = DateTime.UtcNow.Add(
|
||||
_jwtConfiguration.AccessTokenValidity);
|
||||
|
||||
var symmetricSecurityKey = new SymmetricSecurityKey(
|
||||
Encoding.UTF8.GetBytes(_jwtConfiguration.IssuerSigningKey));
|
||||
var signingCredentials = new SigningCredentials(
|
||||
symmetricSecurityKey, SecurityAlgorithms.HmacSha256);
|
||||
|
||||
var jwtSecurityToken = new JwtSecurityToken(
|
||||
issuer: _jwtConfiguration.Issuer,
|
||||
audience: _jwtConfiguration.Audience,
|
||||
claims: claims,
|
||||
expires: expirationDateTimeUtc,
|
||||
signingCredentials: signingCredentials);
|
||||
|
||||
return jwtSecurityToken;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +0,0 @@
|
||||
using MediatR;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Authenticaion.Commands
|
||||
.RenewAccessTokenWithCookie;
|
||||
|
||||
public record RenewAccessTokenWithCookieCommand : IRequest<TokensModel> { }
|
@ -1,26 +0,0 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Authorization;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
using MediatR.Behaviors.Authorization;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Authenticaion.Commands
|
||||
.RenewAccessTokenWithCookie;
|
||||
|
||||
public class RenewAccessTokenWithCookieCommandAuthorizer :
|
||||
AbstractRequestAuthorizer<RenewAccessTokenWithCookieCommand>
|
||||
{
|
||||
private readonly SessionUserService _sessionUserService;
|
||||
|
||||
public RenewAccessTokenWithCookieCommandAuthorizer(
|
||||
SessionUserService currentUserService)
|
||||
{
|
||||
_sessionUserService = currentUserService;
|
||||
}
|
||||
|
||||
public override void BuildPolicy(RenewAccessTokenWithCookieCommand request)
|
||||
{
|
||||
UseRequirement(new MustBeAuthenticatedRequirement
|
||||
{
|
||||
IsAuthenticated = _sessionUserService.IsAuthenticated
|
||||
});
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
using MediatR;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Authenticaion.Commands
|
||||
.RenewAccessTokenWithCookie;
|
||||
|
||||
public class RenewAccessTokenWithCookieCommandHandler :
|
||||
IRequestHandler<RenewAccessTokenWithCookieCommand, TokensModel>
|
||||
{
|
||||
private readonly AuthenticationService _authenticationService;
|
||||
private readonly SessionUserService _sessionUserService;
|
||||
|
||||
public RenewAccessTokenWithCookieCommandHandler(
|
||||
AuthenticationService authenticationService,
|
||||
SessionUserService sessionUserService)
|
||||
{
|
||||
_authenticationService = authenticationService;
|
||||
_sessionUserService = sessionUserService;
|
||||
}
|
||||
|
||||
public async Task<TokensModel> Handle(
|
||||
RenewAccessTokenWithCookieCommand request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return await _authenticationService.RenewAccessTokenAsync(
|
||||
_sessionUserService.RefreshToken, cancellationToken);
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
using FluentValidation;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Authenticaion.Commands
|
||||
.RenewAccessTokenWithCookie;
|
||||
|
||||
public class RenewAccessTokenWithCookieCommandValidator :
|
||||
AbstractValidator<RenewAccessTokenWithCookieCommand>
|
||||
{
|
||||
public RenewAccessTokenWithCookieCommandValidator() { }
|
||||
}
|
@ -1,5 +1,4 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Authorization;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
using MediatR.Behaviors.Authorization;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Authenticaion.Commands.RevokeRefreshToken;
|
||||
@ -7,18 +6,8 @@ namespace cuqmbr.TravelGuide.Application.Authenticaion.Commands.RevokeRefreshTok
|
||||
public class RevokeRefreshTokenCommandAuthorizer :
|
||||
AbstractRequestAuthorizer<RevokeRefreshTokenCommand>
|
||||
{
|
||||
private readonly SessionUserService _sessionUserService;
|
||||
|
||||
public RevokeRefreshTokenCommandAuthorizer(SessionUserService currentUserService)
|
||||
{
|
||||
_sessionUserService = currentUserService;
|
||||
}
|
||||
|
||||
public override void BuildPolicy(RevokeRefreshTokenCommand request)
|
||||
{
|
||||
UseRequirement(new MustBeAuthenticatedRequirement
|
||||
{
|
||||
IsAuthenticated = _sessionUserService.IsAuthenticated
|
||||
});
|
||||
UseRequirement(new AllowAllRequirement());
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
using cuqmbr.TravelGuide.Application.Common.Exceptions;
|
||||
using cuqmbr.TravelGuide.Application.Common.Persistence;
|
||||
using MediatR;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Authenticaion.Commands.RevokeRefreshToken;
|
||||
@ -6,17 +7,36 @@ namespace cuqmbr.TravelGuide.Application.Authenticaion.Commands.RevokeRefreshTok
|
||||
public class RevokeRefreshTokenCommandHandler :
|
||||
IRequestHandler<RevokeRefreshTokenCommand>
|
||||
{
|
||||
private readonly AuthenticationService _authenticationService;
|
||||
private readonly UnitOfWork _unitOfWork;
|
||||
|
||||
public RevokeRefreshTokenCommandHandler(AuthenticationService authenticationService)
|
||||
public RevokeRefreshTokenCommandHandler(UnitOfWork unitOfWork)
|
||||
{
|
||||
_authenticationService = authenticationService;
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public async Task Handle(
|
||||
RevokeRefreshTokenCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
await _authenticationService.RevokeRefreshTokenAsync(
|
||||
request.RefreshToken, cancellationToken);
|
||||
var refreshToken = (await _unitOfWork.RefreshTokenRepository
|
||||
.GetOneAsync(e => e.Value == request.RefreshToken,
|
||||
cancellationToken));
|
||||
|
||||
if (refreshToken == null)
|
||||
{
|
||||
throw new AuthenticationException("Invalid refreshToken");
|
||||
}
|
||||
|
||||
if (!refreshToken.IsActive)
|
||||
{
|
||||
throw new AuthenticationException("RefreshToken already revoked");
|
||||
}
|
||||
|
||||
refreshToken.RevocationTime = DateTimeOffset.UtcNow;
|
||||
|
||||
await _unitOfWork.RefreshTokenRepository
|
||||
.UpdateOneAsync(refreshToken, cancellationToken);
|
||||
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
_unitOfWork.Dispose();
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +0,0 @@
|
||||
using MediatR;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Authenticaion.Commands
|
||||
.RevokeRefreshTokenWithCookie;
|
||||
|
||||
public record RevokeRefreshTokenWithCookieCommand : IRequest { }
|
@ -1,26 +0,0 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Authorization;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
using MediatR.Behaviors.Authorization;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Authenticaion.Commands
|
||||
.RevokeRefreshTokenWithCookie;
|
||||
|
||||
public class RevokeRefreshTokenWithCookieCommandAuthorizer :
|
||||
AbstractRequestAuthorizer<RevokeRefreshTokenWithCookieCommand>
|
||||
{
|
||||
private readonly SessionUserService _sessionUserService;
|
||||
|
||||
public RevokeRefreshTokenWithCookieCommandAuthorizer(
|
||||
SessionUserService currentUserService)
|
||||
{
|
||||
_sessionUserService = currentUserService;
|
||||
}
|
||||
|
||||
public override void BuildPolicy(RevokeRefreshTokenWithCookieCommand request)
|
||||
{
|
||||
UseRequirement(new MustBeAuthenticatedRequirement
|
||||
{
|
||||
IsAuthenticated = _sessionUserService.IsAuthenticated
|
||||
});
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
using MediatR;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Authenticaion.Commands
|
||||
.RevokeRefreshTokenWithCookie;
|
||||
|
||||
public class RevokeRefreshTokenWithCookieCommandHandler :
|
||||
IRequestHandler<RevokeRefreshTokenWithCookieCommand>
|
||||
{
|
||||
private readonly AuthenticationService _authenticationService;
|
||||
private readonly SessionUserService _sessionUserService;
|
||||
|
||||
public RevokeRefreshTokenWithCookieCommandHandler(
|
||||
AuthenticationService authenticationService,
|
||||
SessionUserService sessionUserService)
|
||||
{
|
||||
_authenticationService = authenticationService;
|
||||
_sessionUserService = sessionUserService;
|
||||
}
|
||||
|
||||
public async Task Handle(
|
||||
RevokeRefreshTokenWithCookieCommand request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
await _authenticationService.RevokeRefreshTokenAsync(
|
||||
_sessionUserService.RefreshToken, cancellationToken);
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
using FluentValidation;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Authenticaion.Commands
|
||||
.RevokeRefreshTokenWithCookie;
|
||||
|
||||
public class RevokeRefreshTokenWithCookieCommandValidator :
|
||||
AbstractValidator<RevokeRefreshTokenWithCookieCommand>
|
||||
{
|
||||
public RevokeRefreshTokenWithCookieCommandValidator() { }
|
||||
}
|
@ -4,7 +4,7 @@ namespace cuqmbr.TravelGuide.Application.Authenticaion.Queries.Login;
|
||||
|
||||
public record LoginQuery : IRequest<TokensModel>
|
||||
{
|
||||
public string Email { get; set; }
|
||||
public string EmailOrUsername { get; set; }
|
||||
|
||||
public string Password { get; set; }
|
||||
}
|
||||
|
@ -0,0 +1,12 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Authorization;
|
||||
using MediatR.Behaviors.Authorization;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Authenticaion.Queries.Login;
|
||||
|
||||
public class LoginQueryAuthorizer : AbstractRequestAuthorizer<LoginQuery>
|
||||
{
|
||||
public override void BuildPolicy(LoginQuery request)
|
||||
{
|
||||
UseRequirement(new AllowAllRequirement());
|
||||
}
|
||||
}
|
@ -1,21 +1,140 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Security.Claims;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using cuqmbr.TravelGuide.Application.Common.Exceptions;
|
||||
using cuqmbr.TravelGuide.Application.Common.Persistence;
|
||||
using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using cuqmbr.TravelGuide.Domain.Entities;
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Authenticaion.Queries.Login;
|
||||
|
||||
public class LoginQueryHandler : IRequestHandler<LoginQuery, TokensModel>
|
||||
{
|
||||
private readonly AuthenticationService _authenticationService;
|
||||
private readonly UnitOfWork _unitOfWork;
|
||||
private readonly PasswordHasherService _passwordHasher;
|
||||
private readonly JsonWebTokenConfigurationOptions _jwtConfiguration;
|
||||
|
||||
public LoginQueryHandler(AuthenticationService authenticationService)
|
||||
public LoginQueryHandler(UnitOfWork unitOfWork,
|
||||
PasswordHasherService passwordHasher,
|
||||
IOptions<ConfigurationOptions> configurationOptions)
|
||||
{
|
||||
_authenticationService = authenticationService;
|
||||
_unitOfWork = unitOfWork;
|
||||
_passwordHasher = passwordHasher;
|
||||
_jwtConfiguration = configurationOptions.Value.JsonWebToken;
|
||||
}
|
||||
|
||||
public async Task<TokensModel> Handle(
|
||||
LoginQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
return await _authenticationService.LoginAsync(
|
||||
request.Email, request.Password, cancellationToken);
|
||||
var account = await _unitOfWork.AccountRepository
|
||||
.GetOneAsync(
|
||||
a =>
|
||||
a.Email == request.EmailOrUsername ||
|
||||
a.Username == request.EmailOrUsername,
|
||||
a => a.AccountRoles, cancellationToken);
|
||||
|
||||
if (account == null)
|
||||
{
|
||||
throw new LoginException("No users registered with given email.");
|
||||
}
|
||||
|
||||
var hash = Convert.FromBase64String(account.PasswordHash);
|
||||
var salt = Convert.FromBase64String(account.PasswordSalt);
|
||||
var password = Encoding.UTF8.GetBytes(request.Password);
|
||||
|
||||
var isValidPassword = await _passwordHasher
|
||||
.IsValidHashAsync(hash, password, salt, cancellationToken);
|
||||
|
||||
if (!isValidPassword)
|
||||
{
|
||||
throw new LoginException("Given password is incorrect.");
|
||||
}
|
||||
|
||||
var jwtSecurityToken = await CreateJwtAsync(account, cancellationToken);
|
||||
var accessToken = new JwtSecurityTokenHandler().WriteToken(jwtSecurityToken);
|
||||
|
||||
var refreshToken = (await _unitOfWork.RefreshTokenRepository
|
||||
.GetPageAsync(
|
||||
e =>
|
||||
e.AccountId == account.Id &&
|
||||
e.RevocationTime == null &&
|
||||
e.ExpirationTime > DateTimeOffset.UtcNow,
|
||||
1, int.MaxValue, cancellationToken))
|
||||
.Items.FirstOrDefault();
|
||||
|
||||
if (refreshToken == null)
|
||||
{
|
||||
refreshToken = CreateRefreshToken();
|
||||
refreshToken.AccountId = account.Id;
|
||||
|
||||
await _unitOfWork.RefreshTokenRepository
|
||||
.AddOneAsync(refreshToken, cancellationToken);
|
||||
}
|
||||
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
_unitOfWork.Dispose();
|
||||
|
||||
return new TokensModel(accessToken, refreshToken.Value);
|
||||
}
|
||||
|
||||
private async Task<JwtSecurityToken> CreateJwtAsync(
|
||||
Account account, CancellationToken cancellationToken)
|
||||
{
|
||||
var roleIds = account.AccountRoles.Select(ar => ar.RoleId);
|
||||
|
||||
var roles = (await _unitOfWork.RoleRepository
|
||||
.GetPageAsync(
|
||||
r => roleIds.Contains(r.Id),
|
||||
1, roleIds.Count(), cancellationToken))
|
||||
.Items.Select(r => r.Value);
|
||||
|
||||
var roleClaims = new List<Claim>();
|
||||
foreach (var role in roles)
|
||||
{
|
||||
roleClaims.Add(new Claim("roles", role.Name));
|
||||
}
|
||||
|
||||
var claims = new List<Claim>()
|
||||
{
|
||||
new Claim(JwtRegisteredClaimNames.Sub, account.Guid.ToString()),
|
||||
new Claim(JwtRegisteredClaimNames.Nickname, account.Username),
|
||||
new Claim(JwtRegisteredClaimNames.Email, account.Email)
|
||||
}
|
||||
.Union(roleClaims);
|
||||
|
||||
var expirationDateTimeUtc = DateTime.UtcNow.Add(
|
||||
_jwtConfiguration.AccessTokenValidity);
|
||||
|
||||
var symmetricSecurityKey = new SymmetricSecurityKey(
|
||||
Encoding.UTF8.GetBytes(_jwtConfiguration.IssuerSigningKey));
|
||||
var signingCredentials = new SigningCredentials(
|
||||
symmetricSecurityKey, SecurityAlgorithms.HmacSha256);
|
||||
|
||||
var jwtSecurityToken = new JwtSecurityToken(
|
||||
issuer: _jwtConfiguration.Issuer,
|
||||
audience: _jwtConfiguration.Audience,
|
||||
claims: claims,
|
||||
expires: expirationDateTimeUtc,
|
||||
signingCredentials: signingCredentials);
|
||||
|
||||
return jwtSecurityToken;
|
||||
}
|
||||
|
||||
private RefreshToken CreateRefreshToken()
|
||||
{
|
||||
var token = RandomNumberGenerator.GetBytes(128 / 8);
|
||||
|
||||
return new RefreshToken
|
||||
{
|
||||
Guid = Guid.NewGuid(),
|
||||
Value = Convert.ToBase64String(token),
|
||||
CreationTime = DateTimeOffset.UtcNow,
|
||||
ExpirationTime = DateTimeOffset.UtcNow.Add(
|
||||
_jwtConfiguration.RefreshTokenValidity)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,18 @@
|
||||
using FluentValidation;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Authenticaion.Queries.Login;
|
||||
|
||||
public class LoginQueryValidator : AbstractValidator<LoginQuery>
|
||||
{
|
||||
public LoginQueryValidator()
|
||||
public LoginQueryValidator(IStringLocalizer localizer)
|
||||
{
|
||||
RuleFor(v => v.Email)
|
||||
.NotEmpty().WithMessage("Email address is required.");
|
||||
RuleFor(v => v.EmailOrUsername)
|
||||
.NotEmpty()
|
||||
.WithMessage(localizer["FluentValidation.NotEmpty"]);
|
||||
|
||||
RuleFor(v => v.Password)
|
||||
.NotEmpty().WithMessage("Password is required.");
|
||||
.NotEmpty()
|
||||
.WithMessage(localizer["FluentValidation.NotEmpty"]);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Authorization;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
using cuqmbr.TravelGuide.Application.Common.Models;
|
||||
using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using cuqmbr.TravelGuide.Domain.Enums;
|
||||
using MediatR.Behaviors.Authorization;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Buses.Commands.AddBus;
|
||||
|
@ -1,5 +1,5 @@
|
||||
using MediatR;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Persistence;
|
||||
using cuqmbr.TravelGuide.Application.Common.Persistence;
|
||||
using cuqmbr.TravelGuide.Domain.Entities;
|
||||
using AutoMapper;
|
||||
using cuqmbr.TravelGuide.Application.Common.Exceptions;
|
||||
|
@ -1,4 +1,4 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using FluentValidation;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Authorization;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
using cuqmbr.TravelGuide.Application.Common.Models;
|
||||
using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using cuqmbr.TravelGuide.Domain.Enums;
|
||||
using MediatR.Behaviors.Authorization;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Buses.Commands.DeleteBus;
|
||||
|
@ -1,5 +1,5 @@
|
||||
using MediatR;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Persistence;
|
||||
using cuqmbr.TravelGuide.Application.Common.Persistence;
|
||||
using cuqmbr.TravelGuide.Application.Common.Exceptions;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Buses.Commands.DeleteBus;
|
||||
|
@ -1,6 +1,6 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Authorization;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
using cuqmbr.TravelGuide.Application.Common.Models;
|
||||
using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using cuqmbr.TravelGuide.Domain.Enums;
|
||||
using MediatR.Behaviors.Authorization;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Buses.Commands.UpdateBus;
|
||||
|
@ -1,5 +1,5 @@
|
||||
using MediatR;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Persistence;
|
||||
using cuqmbr.TravelGuide.Application.Common.Persistence;
|
||||
using AutoMapper;
|
||||
using cuqmbr.TravelGuide.Application.Common.Exceptions;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using FluentValidation;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Authorization;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
using cuqmbr.TravelGuide.Application.Common.Models;
|
||||
using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using cuqmbr.TravelGuide.Domain.Enums;
|
||||
using MediatR.Behaviors.Authorization;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Buses.Queries.GetBus;
|
||||
|
@ -1,5 +1,5 @@
|
||||
using MediatR;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Persistence;
|
||||
using cuqmbr.TravelGuide.Application.Common.Persistence;
|
||||
using cuqmbr.TravelGuide.Application.Common.Exceptions;
|
||||
using AutoMapper;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Authorization;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
using cuqmbr.TravelGuide.Application.Common.Models;
|
||||
using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using cuqmbr.TravelGuide.Domain.Enums;
|
||||
using MediatR.Behaviors.Authorization;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Buses.Queries.GetBusesPage;
|
||||
|
@ -1,5 +1,5 @@
|
||||
using MediatR;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Persistence;
|
||||
using cuqmbr.TravelGuide.Application.Common.Persistence;
|
||||
using AutoMapper;
|
||||
using cuqmbr.TravelGuide.Application.Common.Models;
|
||||
using cuqmbr.TravelGuide.Application.Common.Extensions;
|
||||
|
@ -1,4 +1,4 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using FluentValidation;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Authorization;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
using cuqmbr.TravelGuide.Application.Common.Models;
|
||||
using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using cuqmbr.TravelGuide.Domain.Enums;
|
||||
using MediatR.Behaviors.Authorization;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Cities.Commands.AddCity;
|
||||
|
@ -1,5 +1,5 @@
|
||||
using MediatR;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Persistence;
|
||||
using cuqmbr.TravelGuide.Application.Common.Persistence;
|
||||
using cuqmbr.TravelGuide.Domain.Entities;
|
||||
using AutoMapper;
|
||||
using cuqmbr.TravelGuide.Application.Common.Exceptions;
|
||||
|
@ -1,4 +1,4 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using FluentValidation;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Authorization;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
using cuqmbr.TravelGuide.Application.Common.Models;
|
||||
using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using cuqmbr.TravelGuide.Domain.Enums;
|
||||
using MediatR.Behaviors.Authorization;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Cities.Commands.DeleteCity;
|
||||
|
@ -1,5 +1,5 @@
|
||||
using MediatR;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Persistence;
|
||||
using cuqmbr.TravelGuide.Application.Common.Persistence;
|
||||
using cuqmbr.TravelGuide.Application.Common.Exceptions;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Cities.Commands.DeleteCity;
|
||||
|
@ -1,6 +1,6 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Authorization;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
using cuqmbr.TravelGuide.Application.Common.Models;
|
||||
using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using cuqmbr.TravelGuide.Domain.Enums;
|
||||
using MediatR.Behaviors.Authorization;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Cities.Commands.UpdateCity;
|
||||
|
@ -1,5 +1,5 @@
|
||||
using MediatR;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Persistence;
|
||||
using cuqmbr.TravelGuide.Application.Common.Persistence;
|
||||
using AutoMapper;
|
||||
using cuqmbr.TravelGuide.Application.Common.Exceptions;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using FluentValidation;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Authorization;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
using cuqmbr.TravelGuide.Application.Common.Models;
|
||||
using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using cuqmbr.TravelGuide.Domain.Enums;
|
||||
using MediatR.Behaviors.Authorization;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Cities.Queries.GetCitiesPage;
|
||||
|
@ -1,5 +1,5 @@
|
||||
using MediatR;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Persistence;
|
||||
using cuqmbr.TravelGuide.Application.Common.Persistence;
|
||||
using AutoMapper;
|
||||
using cuqmbr.TravelGuide.Application.Common.Models;
|
||||
using cuqmbr.TravelGuide.Application.Common.Extensions;
|
||||
|
@ -1,4 +1,4 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using FluentValidation;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Authorization;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
using cuqmbr.TravelGuide.Application.Common.Models;
|
||||
using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using cuqmbr.TravelGuide.Domain.Enums;
|
||||
using MediatR.Behaviors.Authorization;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Cities.Queries.GetCity;
|
||||
|
@ -1,5 +1,5 @@
|
||||
using MediatR;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Persistence;
|
||||
using cuqmbr.TravelGuide.Application.Common.Persistence;
|
||||
using cuqmbr.TravelGuide.Application.Common.Exceptions;
|
||||
using AutoMapper;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
using MediatR.Behaviors.Authorization;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using cuqmbr.TravelGuide.Application.Common.Models;
|
||||
using cuqmbr.TravelGuide.Domain.Enums;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Authorization;
|
||||
|
||||
|
@ -4,6 +4,14 @@ namespace cuqmbr.TravelGuide.Application.Common.FluentValidation;
|
||||
|
||||
public static class CustomValidators
|
||||
{
|
||||
public static IRuleBuilderOptions<T, string> IsUsername<T>(
|
||||
this IRuleBuilder<T, string> ruleBuilder)
|
||||
{
|
||||
return
|
||||
ruleBuilder
|
||||
.Matches(@"^[a-z0-9-_.]*$");
|
||||
}
|
||||
|
||||
// According to RFC 5321.
|
||||
public static IRuleBuilderOptions<T, string> IsEmail<T>(
|
||||
this IRuleBuilder<T, string> ruleBuilder)
|
||||
|
@ -1,18 +0,0 @@
|
||||
using cuqmbr.TravelGuide.Application.Authenticaion;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
|
||||
public interface AuthenticationService
|
||||
{
|
||||
Task RegisterAsync(string email, string password,
|
||||
CancellationToken cancellationToken);
|
||||
|
||||
Task<TokensModel> LoginAsync(string email, string password,
|
||||
CancellationToken cancellationToken);
|
||||
|
||||
Task<TokensModel> RenewAccessTokenAsync(string refreshToken,
|
||||
CancellationToken cancellationToken);
|
||||
|
||||
Task RevokeRefreshTokenAsync(string refreshToken,
|
||||
CancellationToken cancellationToken);
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Models;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
|
||||
public interface SessionUserService
|
||||
{
|
||||
public int? Id { get; }
|
||||
|
||||
public Guid? Uuid { get; }
|
||||
|
||||
public string? Email { get; }
|
||||
|
||||
public ICollection<IdentityRole> Roles { get; }
|
||||
|
||||
|
||||
public bool IsAuthenticated => Id != null;
|
||||
|
||||
|
||||
public string? AccessToken { get; }
|
||||
|
||||
public string? RefreshToken { get; }
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
using AutoMapper;
|
||||
using cuqmbr.TravelGuide.Application.Common.Interfaces.Services;
|
||||
using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Mappings.Resolvers;
|
||||
|
||||
|
@ -0,0 +1,5 @@
|
||||
using cuqmbr.TravelGuide.Domain.Entities;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Persistence.Repositories;
|
||||
|
||||
public interface AccountRepository : BaseRepository<Account> { }
|
@ -0,0 +1,5 @@
|
||||
using cuqmbr.TravelGuide.Domain.Entities;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Persistence.Repositories;
|
||||
|
||||
public interface AccountRoleRepository : BaseRepository<AccountRole> { }
|
@ -1,6 +1,5 @@
|
||||
using cuqmbr.TravelGuide.Domain.Entities;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Interfaces
|
||||
.Persistence.Repositories;
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Persistence.Repositories;
|
||||
|
||||
public interface AddressRepository : BaseRepository<Address> { }
|
@ -1,6 +1,5 @@
|
||||
using cuqmbr.TravelGuide.Domain.Entities;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Interfaces
|
||||
.Persistence.Repositories;
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Persistence.Repositories;
|
||||
|
||||
public interface AircraftRepository : BaseRepository<Aircraft> { }
|
@ -2,8 +2,7 @@ using System.Linq.Expressions;
|
||||
using cuqmbr.TravelGuide.Application.Common.Models;
|
||||
using cuqmbr.TravelGuide.Domain.Entities;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Interfaces
|
||||
.Persistence.Repositories;
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Persistence.Repositories;
|
||||
|
||||
public interface BaseRepository<TEntity>
|
||||
where TEntity : EntityBase
|
@ -1,6 +1,5 @@
|
||||
using cuqmbr.TravelGuide.Domain.Entities;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Interfaces
|
||||
.Persistence.Repositories;
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Persistence.Repositories;
|
||||
|
||||
public interface BusRepository : BaseRepository<Bus> { }
|
@ -1,6 +1,5 @@
|
||||
using cuqmbr.TravelGuide.Domain.Entities;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Interfaces
|
||||
.Persistence.Repositories;
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Persistence.Repositories;
|
||||
|
||||
public interface CityRepository : BaseRepository<City> { }
|
@ -1,6 +1,6 @@
|
||||
using cuqmbr.TravelGuide.Domain.Entities;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Interfaces
|
||||
namespace cuqmbr.TravelGuide.Application.Common
|
||||
.Persistence.Repositories;
|
||||
|
||||
public interface CompanyRepository : BaseRepository<Company> { }
|
@ -1,6 +1,5 @@
|
||||
using cuqmbr.TravelGuide.Domain.Entities;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Interfaces
|
||||
.Persistence.Repositories;
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Persistence.Repositories;
|
||||
|
||||
public interface CountryRepository : BaseRepository<Country> { }
|
@ -1,6 +1,6 @@
|
||||
using cuqmbr.TravelGuide.Domain.Entities;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Interfaces
|
||||
namespace cuqmbr.TravelGuide.Application.Common
|
||||
.Persistence.Repositories;
|
||||
|
||||
public interface EmployeeRepository : BaseRepository<Employee> { }
|
@ -0,0 +1,5 @@
|
||||
using cuqmbr.TravelGuide.Domain.Entities;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Persistence.Repositories;
|
||||
|
||||
public interface RefreshTokenRepository : BaseRepository<RefreshToken> { }
|
@ -1,6 +1,5 @@
|
||||
using cuqmbr.TravelGuide.Domain.Entities;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Interfaces
|
||||
.Persistence.Repositories;
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Persistence.Repositories;
|
||||
|
||||
public interface RegionRepository : BaseRepository<Region> { }
|
@ -0,0 +1,5 @@
|
||||
using cuqmbr.TravelGuide.Domain.Entities;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Persistence.Repositories;
|
||||
|
||||
public interface RoleRepository : BaseRepository<Role> { }
|
@ -1,6 +1,6 @@
|
||||
using cuqmbr.TravelGuide.Domain.Entities;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Interfaces
|
||||
namespace cuqmbr.TravelGuide.Application.Common
|
||||
.Persistence.Repositories;
|
||||
|
||||
public interface RouteAddressDetailRepository :
|
@ -1,7 +1,6 @@
|
||||
using cuqmbr.TravelGuide.Domain.Entities;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Interfaces
|
||||
.Persistence.Repositories;
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Persistence.Repositories;
|
||||
|
||||
public interface RouteAddressRepository :
|
||||
BaseRepository<RouteAddress> { }
|
@ -1,6 +1,5 @@
|
||||
using cuqmbr.TravelGuide.Domain.Entities;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Interfaces
|
||||
.Persistence.Repositories;
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Persistence.Repositories;
|
||||
|
||||
public interface RouteRepository : BaseRepository<Route> { }
|
@ -1,6 +1,6 @@
|
||||
using cuqmbr.TravelGuide.Domain.Entities;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Interfaces
|
||||
namespace cuqmbr.TravelGuide.Application.Common
|
||||
.Persistence.Repositories;
|
||||
|
||||
public interface TicketGroupRepository : BaseRepository<TicketGroup> { }
|
@ -1,6 +1,6 @@
|
||||
using cuqmbr.TravelGuide.Domain.Entities;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Interfaces
|
||||
namespace cuqmbr.TravelGuide.Application.Common
|
||||
.Persistence.Repositories;
|
||||
|
||||
public interface TicketRepository : BaseRepository<Ticket> { }
|
@ -1,6 +1,5 @@
|
||||
using cuqmbr.TravelGuide.Domain.Entities;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Interfaces
|
||||
.Persistence.Repositories;
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Persistence.Repositories;
|
||||
|
||||
public interface TrainRepository : BaseRepository<Train> { }
|
@ -0,0 +1,6 @@
|
||||
using cuqmbr.TravelGuide.Domain.Entities;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Common.Persistence.Repositories;
|
||||
|
||||
public interface VehicleEnrollmentEmployeeRepository :
|
||||
BaseRepository<VehicleEnrollmentEmployee> { }
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user