Added authentication and authorization, updated dependency injections, removed hard-coded connection string
This commit is contained in:
@@ -14,4 +14,8 @@
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.0-preview.7.24405.7" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="DataAccessingServices\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
namespace ApplicationLayer.AuthServices.LoginService.Exceptions
|
||||
{
|
||||
public class IncorrectLoginDataException() : Exception("Incorrect email or password");
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using ApplicationLayer.AuthServices.Requests;
|
||||
|
||||
namespace ApplicationLayer.AuthServices.LoginService
|
||||
{
|
||||
/// Handles <see cref="UserLoginRequest"/>
|
||||
public interface ILoginService
|
||||
{
|
||||
/// Handle <see cref="UserLoginRequest"/>
|
||||
/// <returns>JWT-token</returns>
|
||||
Task<string> LoginAsync(UserLoginRequest request, CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using ApplicationLayer.AuthServices.LoginService.Exceptions;
|
||||
using ApplicationLayer.AuthServices.NeededServices;
|
||||
using ApplicationLayer.AuthServices.Requests;
|
||||
|
||||
namespace ApplicationLayer.AuthServices.LoginService
|
||||
{
|
||||
/// <inheritdoc cref="ILoginService"/>
|
||||
public class LoginService(IUsersRepository users, ITokenGenerator tokenGenerator) : ILoginService
|
||||
{
|
||||
async Task<string> ILoginService.LoginAsync(UserLoginRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var user = await users.FindByEmailAsync(request.Email, cancellationToken);
|
||||
if (user is null || user.Password != request.Password)
|
||||
{
|
||||
throw new IncorrectLoginDataException();
|
||||
}
|
||||
|
||||
return tokenGenerator.CreateToken(user);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using Domains.Users;
|
||||
|
||||
namespace ApplicationLayer.AuthServices.NeededServices
|
||||
{
|
||||
public interface ITokenGenerator
|
||||
{
|
||||
string CreateToken(User user);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using ApplicationLayer.GeneralNeededServices;
|
||||
using Domains.Users;
|
||||
|
||||
namespace ApplicationLayer.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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
using ApplicationLayer.AuthServices.Requests;
|
||||
|
||||
namespace ApplicationLayer.AuthServices.RegisterService.Exceptions
|
||||
{
|
||||
public class UserAlreadyExistsException(RegisterApplicantRequest request) : Exception($"User with email '{request.Email}' already exists");
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using ApplicationLayer.AuthServices.Requests;
|
||||
|
||||
namespace ApplicationLayer.AuthServices.RegisterService
|
||||
{
|
||||
/// Handles <see cref="RegisterApplicantRequest"/>
|
||||
public interface IRegisterService
|
||||
{
|
||||
/// Handle <see cref="RegisterApplicantRequest"/>
|
||||
Task Register(RegisterApplicantRequest request, CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using ApplicationLayer.AuthServices.NeededServices;
|
||||
using ApplicationLayer.AuthServices.RegisterService.Exceptions;
|
||||
using ApplicationLayer.AuthServices.Requests;
|
||||
using Domains.Users;
|
||||
|
||||
namespace ApplicationLayer.AuthServices.RegisterService
|
||||
{
|
||||
/// <inheritdoc cref="IRegisterService"/>
|
||||
public class RegisterService(IUsersRepository users) : IRegisterService
|
||||
{
|
||||
async Task IRegisterService.Register(RegisterApplicantRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
if (await users.FindByEmailAsync(request.Email, cancellationToken) is not null)
|
||||
{
|
||||
throw new UserAlreadyExistsException(request);
|
||||
}
|
||||
|
||||
//TODO mapper
|
||||
var user = new User
|
||||
{
|
||||
Email = request.Email,
|
||||
Password = request.Password,
|
||||
Role = Role.Applicant
|
||||
};
|
||||
|
||||
await users.AddAsync(user, cancellationToken);
|
||||
await users.SaveAsync(cancellationToken);
|
||||
users.GetAllAsync(cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
namespace ApplicationLayer.AuthServices.Requests
|
||||
{
|
||||
public record RegisterApplicantRequest(string Email, string Password);
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
namespace ApplicationLayer.AuthServices.Requests
|
||||
{
|
||||
public record UserLoginRequest(string Email, string Password);
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
using ApplicationLayer.GeneralNeededServices;
|
||||
using Domains.ApplicantDomain;
|
||||
|
||||
namespace ApplicationLayer.Applicants.NeededServices;
|
||||
namespace ApplicationLayer.DataAccessingServices.Applicants.NeededServices;
|
||||
|
||||
/// Repository pattern for <see cref="Applicant"/>
|
||||
public interface IApplicantsRepository : IGenericRepository<Applicant> { }
|
||||
public interface IApplicantsRepository : IGenericRepository<Applicant>;
|
||||
@@ -0,0 +1,6 @@
|
||||
using ApplicationLayer.GeneralNeededServices;
|
||||
using Domains.LocationDomain;
|
||||
|
||||
namespace ApplicationLayer.DataAccessingServices.Locations.NeededServices;
|
||||
|
||||
public interface ICitiesRepository : IGenericRepository<City>;
|
||||
@@ -1,6 +1,6 @@
|
||||
using ApplicationLayer.GeneralNeededServices;
|
||||
using Domains.LocationDomain;
|
||||
|
||||
namespace ApplicationLayer.Locations.NeededServices;
|
||||
namespace ApplicationLayer.DataAccessingServices.Locations.NeededServices;
|
||||
|
||||
public interface ICountriesRepository : IGenericRepository<Country> { }
|
||||
public interface ICountriesRepository : IGenericRepository<Country>;
|
||||
@@ -1,7 +1,7 @@
|
||||
using ApplicationLayer.VisaApplications.Requests;
|
||||
using ApplicationLayer.DataAccessingServices.VisaApplications.Requests;
|
||||
using Domains.VisaApplicationDomain;
|
||||
|
||||
namespace ApplicationLayer.VisaApplications.Handlers;
|
||||
namespace ApplicationLayer.DataAccessingServices.VisaApplications.Handlers;
|
||||
|
||||
public interface IVisaApplicationsRequestHandler
|
||||
{
|
||||
@@ -1,11 +1,11 @@
|
||||
using ApplicationLayer.Locations.NeededServices;
|
||||
using ApplicationLayer.VisaApplications.Models;
|
||||
using ApplicationLayer.VisaApplications.NeededServices;
|
||||
using ApplicationLayer.VisaApplications.Requests;
|
||||
using ApplicationLayer.DataAccessingServices.Locations.NeededServices;
|
||||
using ApplicationLayer.DataAccessingServices.VisaApplications.Models;
|
||||
using ApplicationLayer.DataAccessingServices.VisaApplications.NeededServices;
|
||||
using ApplicationLayer.DataAccessingServices.VisaApplications.Requests;
|
||||
using Domains.ApplicantDomain;
|
||||
using Domains.VisaApplicationDomain;
|
||||
|
||||
namespace ApplicationLayer.VisaApplications.Handlers;
|
||||
namespace ApplicationLayer.DataAccessingServices.VisaApplications.Handlers;
|
||||
|
||||
/// Handles visa requests
|
||||
public class VisaApplicationRequestsHandler(
|
||||
@@ -64,6 +64,7 @@ public class VisaApplicationRequestsHandler(
|
||||
};
|
||||
|
||||
await applications.AddAsync(visaApplication, cancellationToken);
|
||||
await applications.SaveAsync(cancellationToken);
|
||||
}
|
||||
|
||||
private async Task<PastVisit> ConvertPastVisitModelToPastVisit(PastVisitModel model, CancellationToken cancellationToken)
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace ApplicationLayer.VisaApplications.Models;
|
||||
namespace ApplicationLayer.DataAccessingServices.VisaApplications.Models;
|
||||
|
||||
public class AddressModel
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace ApplicationLayer.VisaApplications.Models
|
||||
namespace ApplicationLayer.DataAccessingServices.VisaApplications.Models
|
||||
{
|
||||
public class PastVisitModel
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace ApplicationLayer.VisaApplications.Models;
|
||||
namespace ApplicationLayer.DataAccessingServices.VisaApplications.Models;
|
||||
|
||||
public class PlaceOfWorkModel
|
||||
{
|
||||
@@ -1,6 +1,6 @@
|
||||
using ApplicationLayer.GeneralNeededServices;
|
||||
using Domains.VisaApplicationDomain;
|
||||
|
||||
namespace ApplicationLayer.VisaApplications.NeededServices;
|
||||
namespace ApplicationLayer.DataAccessingServices.VisaApplications.NeededServices;
|
||||
|
||||
public interface IVisaApplicationsRepository : IGenericRepository<VisaApplication> { }
|
||||
public interface IVisaApplicationsRepository : IGenericRepository<VisaApplication>;
|
||||
@@ -1,8 +1,8 @@
|
||||
using ApplicationLayer.VisaApplications.Models;
|
||||
using ApplicationLayer.DataAccessingServices.VisaApplications.Models;
|
||||
using Domains.ApplicantDomain;
|
||||
using Domains.VisaApplicationDomain;
|
||||
|
||||
namespace ApplicationLayer.VisaApplications.Requests;
|
||||
namespace ApplicationLayer.DataAccessingServices.VisaApplications.Requests;
|
||||
|
||||
/// Model of visa request from user
|
||||
public record VisaApplicationCreateRequest(
|
||||
@@ -1,4 +1,6 @@
|
||||
using ApplicationLayer.VisaApplications.Handlers;
|
||||
using ApplicationLayer.AuthServices.LoginService;
|
||||
using ApplicationLayer.AuthServices.RegisterService;
|
||||
using ApplicationLayer.DataAccessingServices.VisaApplications.Handlers;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace ApplicationLayer;
|
||||
@@ -11,6 +13,9 @@ public static class DependencyInjection
|
||||
{
|
||||
services.AddScoped<IVisaApplicationsRequestHandler, VisaApplicationRequestsHandler>();
|
||||
|
||||
services.AddScoped<IRegisterService, RegisterService>();
|
||||
services.AddScoped<ILoginService, LoginService>();
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace ApplicationLayer.GeneralNeededServices
|
||||
{
|
||||
public interface IDateTimeProvider
|
||||
{
|
||||
/// Returns current date and time
|
||||
DateTime Now();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
using ApplicationLayer.GeneralNeededServices;
|
||||
using Domains.LocationDomain;
|
||||
|
||||
namespace ApplicationLayer.Locations.NeededServices;
|
||||
|
||||
public interface ICitiesRepository : IGenericRepository<City> { }
|
||||
13
SchengenVisaApi/Domains/Users/Role.cs
Normal file
13
SchengenVisaApi/Domains/Users/Role.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace Domains.Users
|
||||
{
|
||||
/// Role of <see cref="User"/>
|
||||
public enum Role
|
||||
{
|
||||
/// Requests visa applications
|
||||
Applicant,
|
||||
/// Approves or declines applications
|
||||
ApprovingAuthority,
|
||||
/// Manages approving authorities
|
||||
Admin
|
||||
}
|
||||
}
|
||||
14
SchengenVisaApi/Domains/Users/User.cs
Normal file
14
SchengenVisaApi/Domains/Users/User.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
namespace Domains.Users
|
||||
{
|
||||
public class User : IEntity
|
||||
{
|
||||
/// Unique Identifier of <see cref="User"/>
|
||||
public Guid Id { get; private set; } = Guid.NewGuid();
|
||||
|
||||
public Role Role { get; set; }
|
||||
|
||||
public string Email { get; set; } = null!;
|
||||
|
||||
public string Password { get; set; } = null!;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
30
SchengenVisaApi/Infrastructure/Auth/TokenGenerator.cs
Normal file
30
SchengenVisaApi/Infrastructure/Auth/TokenGenerator.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
|
||||
namespace Infrastructure.Auth
|
||||
{
|
||||
public record TokenGeneratorOptions(string Issuer, string Audience, TimeSpan ValidTime, SigningCredentials Credentials);
|
||||
}
|
||||
10
SchengenVisaApi/Infrastructure/Common/DateTimeProvider.cs
Normal file
10
SchengenVisaApi/Infrastructure/Common/DateTimeProvider.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
using ApplicationLayer.GeneralNeededServices;
|
||||
|
||||
namespace Infrastructure.Common
|
||||
{
|
||||
/// Implements <see cref="IDateTimeProvider"/>
|
||||
public class DateTimeProvider : IDateTimeProvider
|
||||
{
|
||||
DateTime IDateTimeProvider.Now() => DateTime.Now;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using ApplicationLayer.Applicants.NeededServices;
|
||||
using ApplicationLayer.DataAccessingServices.Applicants.NeededServices;
|
||||
using Domains.ApplicantDomain;
|
||||
using Infrastructure.Database.Generic;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using ApplicationLayer.Locations.NeededServices;
|
||||
using ApplicationLayer.DataAccessingServices.Locations.NeededServices;
|
||||
using Domains.LocationDomain;
|
||||
using Infrastructure.Database.Generic;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using ApplicationLayer.Locations.NeededServices;
|
||||
using ApplicationLayer.DataAccessingServices.Locations.NeededServices;
|
||||
using Domains.LocationDomain;
|
||||
using Infrastructure.Database.Generic;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using ApplicationLayer.VisaApplications.NeededServices;
|
||||
using ApplicationLayer.DataAccessingServices.VisaApplications.NeededServices;
|
||||
using Domains.VisaApplicationDomain;
|
||||
using Infrastructure.Database.Generic;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
using ApplicationLayer.AuthServices.LoginService;
|
||||
using ApplicationLayer.AuthServices.RegisterService;
|
||||
using ApplicationLayer.AuthServices.Requests;
|
||||
using Microsoft.AspNetCore.Identity.Data;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace SchengenVisaApi.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("auth")]
|
||||
public class UsersController(IRegisterService registerService, ILoginService loginService) : Controller
|
||||
{
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> Register(RegisterApplicantRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
await registerService.Register(request, cancellationToken);
|
||||
return Created();
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> Login(string email, string password, CancellationToken cancellationToken)
|
||||
{
|
||||
var result = await loginService.LoginAsync(new UserLoginRequest(email, password), cancellationToken);
|
||||
return Ok(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
using ApplicationLayer.VisaApplications.Handlers;
|
||||
using ApplicationLayer.VisaApplications.Requests;
|
||||
using ApplicationLayer.DataAccessingServices.VisaApplications.Handlers;
|
||||
using ApplicationLayer.DataAccessingServices.VisaApplications.Requests;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace SchengenVisaApi.Controllers;
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using ApplicationLayer;
|
||||
using Infrastructure;
|
||||
using Infrastructure.Auth;
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
|
||||
namespace SchengenVisaApi;
|
||||
|
||||
@@ -8,21 +12,61 @@ namespace SchengenVisaApi;
|
||||
public static class DependencyInjection
|
||||
{
|
||||
/// Add needed services
|
||||
public static IServiceCollection RegisterServices(this IServiceCollection services)
|
||||
public static void RegisterServices(this WebApplicationBuilder builder)
|
||||
{
|
||||
services
|
||||
.AddInfrastructure()
|
||||
var config = builder.Configuration;
|
||||
var environment = builder.Environment;
|
||||
|
||||
builder.Services
|
||||
.AddInfrastructure(config, environment.IsDevelopment())
|
||||
.AddApplicationLayer()
|
||||
.AddPresentation();
|
||||
.AddAuth(config)
|
||||
.AddPresentation(environment);
|
||||
}
|
||||
|
||||
/// Add services needed for Presentation layer
|
||||
private static void AddPresentation(this IServiceCollection services,
|
||||
IWebHostEnvironment environment)
|
||||
{
|
||||
if (environment.IsDevelopment())
|
||||
{
|
||||
services.AddSwagger();
|
||||
}
|
||||
|
||||
services.AddControllers();
|
||||
}
|
||||
|
||||
/// Adds authentication, authorization and token generator
|
||||
private static IServiceCollection AddAuth(this IServiceCollection services, IConfigurationManager configurationManager)
|
||||
{
|
||||
var parameters = new TokenValidationParameters
|
||||
{
|
||||
ValidIssuer = configurationManager["JwtSettings:Issuer"],
|
||||
ValidAudience = configurationManager["JwtSettings:Audience"],
|
||||
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configurationManager["JwtSettings:Key"]!)),
|
||||
ValidateIssuer = true,
|
||||
ValidateAudience = true,
|
||||
ValidateLifetime = true,
|
||||
ValidateIssuerSigningKey = true
|
||||
};
|
||||
|
||||
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
||||
.AddJwtBearer(opts => opts.TokenValidationParameters = parameters);
|
||||
services.AddAuthorization();
|
||||
|
||||
services.AddTokenGenerator(new TokenGeneratorOptions(
|
||||
Issuer: parameters.ValidIssuer!,
|
||||
Audience: parameters.ValidAudience!,
|
||||
Credentials: new SigningCredentials(parameters.IssuerSigningKey, SecurityAlgorithms.HmacSha256),
|
||||
ValidTime: TimeSpan.FromMinutes(30)
|
||||
));
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
/// Add services needed for Presentation layer
|
||||
private static void AddPresentation(this IServiceCollection services)
|
||||
/// Add swagger
|
||||
private static void AddSwagger(this IServiceCollection services)
|
||||
{
|
||||
services.AddControllers();
|
||||
services.AddEndpointsApiExplorer();
|
||||
services.AddSwaggerGen(options =>
|
||||
{
|
||||
var xmlFilename = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
namespace SchengenVisaApi;
|
||||
|
||||
#pragma warning disable CS1591
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
builder.Services.RegisterServices();
|
||||
builder.RegisterServices();
|
||||
|
||||
var app = builder.Build();
|
||||
app.ConfigurePipelineRequest();
|
||||
@@ -13,4 +14,4 @@ public class Program
|
||||
app.Run();
|
||||
}
|
||||
}
|
||||
#pragma warning restore CS1591
|
||||
#pragma warning restore CS1591
|
||||
|
||||
@@ -11,8 +11,11 @@ public static class PipelineRequest
|
||||
|
||||
app.UseHttpsRedirection();
|
||||
|
||||
app.UseAuthentication()
|
||||
.UseAuthorization();
|
||||
|
||||
app.MapControllers();
|
||||
|
||||
return app;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,5 +5,16 @@
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
"AllowedHosts": "*",
|
||||
|
||||
"ConnectionStrings": {
|
||||
"developmentDB": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=visadb;Integrated Security=True;",
|
||||
"normal'naya db": ""
|
||||
},
|
||||
|
||||
"JwtSettings": {
|
||||
"Issuer":"visaAPI",
|
||||
"Audience":"visaClient",
|
||||
"Key": "frsjiajfapojrpwauflakpiowaidoaplakrf"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user