Added authentication and authorization, updated dependency injections, removed hard-coded connection string

This commit is contained in:
2024-08-17 16:28:35 +03:00
parent 026a104131
commit 7cbe3d9698
44 changed files with 419 additions and 49 deletions

View File

@@ -0,0 +1,24 @@
using System.IdentityModel.Tokens.Jwt;
using ApplicationLayer.AuthServices.NeededServices;
using ApplicationLayer.GeneralNeededServices;
using Microsoft.Extensions.DependencyInjection;
namespace Infrastructure.Auth
{
public static class ServiceCollectionsExtensions
{
public static IServiceCollection AddTokenGenerator(this IServiceCollection services, TokenGeneratorOptions options)
{
services.AddSingleton<JwtSecurityTokenHandler>();
services.AddSingleton<ITokenGenerator, TokenGenerator>(provider =>
{
var tokenHandler = provider.GetRequiredService<JwtSecurityTokenHandler>();
var dateTimeProvider = provider.GetRequiredService<IDateTimeProvider>();
return new TokenGenerator(options, tokenHandler, dateTimeProvider);
});
return services;
}
}
}

View File

@@ -0,0 +1,30 @@
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using ApplicationLayer.AuthServices.NeededServices;
using ApplicationLayer.GeneralNeededServices;
using Domains.Users;
namespace Infrastructure.Auth
{
public class TokenGenerator(TokenGeneratorOptions options, JwtSecurityTokenHandler tokenHandler, IDateTimeProvider dateTimeProvider)
: ITokenGenerator
{
public string CreateToken(User user)
{
var claims = new List<Claim>
{
new(ClaimTypes.Role, user.Role.ToString()),
new(ClaimTypes.Email, user.Email)
};
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);
}
}
}

View File

@@ -0,0 +1,6 @@
using Microsoft.IdentityModel.Tokens;
namespace Infrastructure.Auth
{
public record TokenGeneratorOptions(string Issuer, string Audience, TimeSpan ValidTime, SigningCredentials Credentials);
}

View File

@@ -0,0 +1,10 @@
using ApplicationLayer.GeneralNeededServices;
namespace Infrastructure.Common
{
/// Implements <see cref="IDateTimeProvider"/>
public class DateTimeProvider : IDateTimeProvider
{
DateTime IDateTimeProvider.Now() => DateTime.Now;
}
}

View File

@@ -1,4 +1,4 @@
using ApplicationLayer.Applicants.NeededServices;
using ApplicationLayer.DataAccessingServices.Applicants.NeededServices;
using Domains.ApplicantDomain;
using Infrastructure.Database.Generic;
using Microsoft.EntityFrameworkCore;

View File

@@ -1,4 +1,4 @@
using ApplicationLayer.Locations.NeededServices;
using ApplicationLayer.DataAccessingServices.Locations.NeededServices;
using Domains.LocationDomain;
using Infrastructure.Database.Generic;
using Microsoft.EntityFrameworkCore;

View File

@@ -1,4 +1,4 @@
using ApplicationLayer.Locations.NeededServices;
using ApplicationLayer.DataAccessingServices.Locations.NeededServices;
using Domains.LocationDomain;
using Infrastructure.Database.Generic;
using Microsoft.EntityFrameworkCore;

View File

@@ -0,0 +1,22 @@
using Domains.Users;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Infrastructure.Database.Users.Configuration
{
public class UserConfiguration : IEntityTypeConfiguration<User>
{
public void Configure(EntityTypeBuilder<User> entity)
{
entity.Property(u => u.Email)
.IsUnicode(false)
.HasMaxLength(254);
entity.HasIndex(u => u.Email).IsUnique();
entity.Property(u => u.Password)
.IsUnicode(false)
.HasMaxLength(50);
}
}
}

View File

@@ -0,0 +1,17 @@
using ApplicationLayer.AuthServices.NeededServices;
using Domains.Users;
using Infrastructure.Database.Generic;
using Microsoft.EntityFrameworkCore;
namespace Infrastructure.Database.Users.Repositories
{
/// <inheritdoc cref="IUsersRepository"/>
public class UsersRepository(IGenericReader reader, IGenericWriter writer, IUnitOfWork unitOfWork)
: GenericRepository<User>(reader, writer, unitOfWork), IUsersRepository
{
async Task<User?> IUsersRepository.FindByEmailAsync(string email, CancellationToken cancellationToken)
{
return await LoadDomain().SingleOrDefaultAsync(u => u.Email == email, cancellationToken);
}
}
}

View File

@@ -1,4 +1,4 @@
using ApplicationLayer.VisaApplications.NeededServices;
using ApplicationLayer.DataAccessingServices.VisaApplications.NeededServices;
using Domains.VisaApplicationDomain;
using Infrastructure.Database.Generic;
using Microsoft.EntityFrameworkCore;

View File

@@ -1,13 +1,19 @@
using ApplicationLayer.Applicants.NeededServices;
using ApplicationLayer.Locations.NeededServices;
using ApplicationLayer.VisaApplications.NeededServices;
using ApplicationLayer.AuthServices.NeededServices;
using ApplicationLayer.DataAccessingServices.Applicants.NeededServices;
using ApplicationLayer.DataAccessingServices.Locations.NeededServices;
using ApplicationLayer.DataAccessingServices.VisaApplications.NeededServices;
using ApplicationLayer.GeneralNeededServices;
using Infrastructure.Auth;
using Infrastructure.Common;
using Infrastructure.Database;
using Infrastructure.Database.Applicants.Repositories;
using Infrastructure.Database.Generic;
using Infrastructure.Database.Locations.Repositories.Cities;
using Infrastructure.Database.Locations.Repositories.Countries;
using Infrastructure.Database.Users.Repositories;
using Infrastructure.Database.VisaApplications.Repositories;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using DbContext = Infrastructure.Database.DbContext;
@@ -17,11 +23,14 @@ namespace Infrastructure;
public static class DependencyInjection
{
/// Add services needed for Infrastructure layer
public static IServiceCollection AddInfrastructure(this IServiceCollection services)
public static IServiceCollection AddInfrastructure(this IServiceCollection services,
IConfigurationManager configurationManager,
bool isDevelopment)
{
//TODO строка подключения
var databaseName = isDevelopment ? "developmentDB" : "normal'naya database";
services.AddDbContextFactory<DbContext>(opts =>
opts.UseSqlServer("Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=visadb;Integrated Security=True;"));
opts.UseSqlServer(configurationManager.GetConnectionString(databaseName)));
services.AddScoped<IGenericReader>(serviceProvider => serviceProvider.GetRequiredService<DbContext>());
services.AddScoped<IGenericWriter>(serviceProvider => serviceProvider.GetRequiredService<DbContext>());
@@ -31,6 +40,9 @@ public static class DependencyInjection
services.AddScoped<IVisaApplicationsRepository, VisaApplicationsRepository>();
services.AddScoped<ICitiesRepository, CitiesRepository>();
services.AddScoped<ICountriesRepository, CountriesRepository>();
services.AddScoped<IUsersRepository, UsersRepository>();
services.AddSingleton<IDateTimeProvider, DateTimeProvider>();
return services;
}

View File

@@ -11,6 +11,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.0-preview.7.24405.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="9.0.0-preview.7.24405.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.0-preview.7.24405.3" />