Skip to content

Commit

Permalink
feat(authentication,dotnet8): bumped dotnet and implemented auth
Browse files Browse the repository at this point in the history
  • Loading branch information
Samuel Verdejo committed Nov 16, 2023
1 parent b5033fc commit 1140e93
Show file tree
Hide file tree
Showing 32 changed files with 401 additions and 53 deletions.
15 changes: 15 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "chrome",
"request": "launch",
"name": "Launch Chrome against localhost",
"url": "http://localhost:8080",
"webRoot": "${workspaceFolder}"
}
]
}
4 changes: 2 additions & 2 deletions Application/Application.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
<PackageReference Include="Mapster.DependencyInjection" Version="1.0.1" />
<PackageReference Include="MediatR" Version="12.1.1" />
<PackageReference Include="MediatR.Contracts" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0-rc.2.23479.6" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0-rc.2.23479.6" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Domain\Domain.csproj" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using Application.Shared.Command;
using Domain.Budgets;

namespace Application;
namespace Application.Budgets;

public class DeleteBudgetCommandHandler : ICommandHandler<DeleteBudgetCommand>
{
Expand Down
8 changes: 8 additions & 0 deletions Application/Shared/Services/IIdentityService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using Domain;

namespace Application;

public interface IIdentityService
{
public Task<string> GenerateToken(User user);
}
33 changes: 33 additions & 0 deletions Application/Users/Commands/Handlers/LoginCommandHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System.Reflection.Metadata;
using Application.Shared.Command;
using Domain;

namespace Application;

public sealed class LoginCommandHandler : ICommandHandler<LoginCommand, string>
{
private readonly IUserRepository _userRepository;

private readonly IIdentityService _identityService;

public LoginCommandHandler(IUserRepository userRepository, IIdentityService identityService)
{
_userRepository = userRepository;
_identityService = identityService;
}

public async Task<string> Handle(LoginCommand request, CancellationToken cancellationToken = default)
{
var mail = UserMail.Create(request.Mail);
var criteria = new UserByMailCriteria(mail);

User? user = await _userRepository.MatchFirstOrDefault(criteria);

if (user is null)
throw new UserNotFoundException(mail);

var token = await _identityService.GenerateToken(user);

return token;
}
}
5 changes: 5 additions & 0 deletions Application/Users/Commands/LoginCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
using Application.Shared.Command;

namespace Application;

public sealed record LoginCommand(string Mail) : ICommand<string>;
8 changes: 3 additions & 5 deletions Domain/Budgets/Entities/Alerts/DateBudgetAlert.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using Domain.Budgets;

namespace Domain;
namespace Domain.Budgets;

public class DateBudgetAlert : BudgetAlert
{
Expand All @@ -16,10 +14,10 @@ protected DateBudgetAlert(DateTime alertingDate) =>
public static DateBudgetAlert Create(DateTime alertingDate) =>
new(alertingDate);

public override bool Eval(Budget.Budget budget) =>
public override bool Eval(Budget budget) =>
DateTime.Now > AlertingDate;

public override AlertEvent GenerateEvent(Budget.Budget budget)
public override AlertEvent GenerateEvent(Budget budget)
=> new DateOverdueAlertEvent()
{
FiredAt = DateTime.Now,
Expand Down
25 changes: 25 additions & 0 deletions Domain/Users/Entities/User.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using Domain.Shared.Base;

namespace Domain;

public class User : AggregateRoot<User>
{
public UserId Id { get; private set; }

public UserMail Mail { get; private set; }

protected User(UserId id, UserMail mail)
{
Id = id;
Mail = mail;
}

public static User Create(UserId id, UserMail mail)
{
var user = new User(id, mail);

user.RecordEvent(new UserCreatedEvent(id.Value, mail.Value));

return user;
}
}
14 changes: 14 additions & 0 deletions Domain/Users/Errors/UserNotFoundException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using Domain.Shared.Base;

namespace Domain;

public class UserNotFoundException : DomainException
{
public UserNotFoundException(UserMail mail) : base($"The user with mail [{mail.Value}] has not been found in the database.")
{
}

public UserNotFoundException(UserId id) : base($"The user with id [{id.Value}] has not been found in the database.")
{
}
}
5 changes: 5 additions & 0 deletions Domain/Users/Events/UserCreatedEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
using Domain.Shared.Base;

namespace Domain;

public sealed record UserCreatedEvent(Guid id, string Mail) : IDomainEvent;
11 changes: 11 additions & 0 deletions Domain/Users/Repository/Criteria/UserByMailCriteria.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System.Linq.Expressions;
using Domain.Shared.Base;

namespace Domain;

public class UserByMailCriteria : Criteria<User>
{
public UserByMailCriteria(UserMail mail) : base(user => user.Mail == mail)
{
}
}
7 changes: 7 additions & 0 deletions Domain/Users/Repository/IUserRepository.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
using Domain.Shared.Base;

namespace Domain;

public interface IUserRepository : IRepository<User>
{
}
12 changes: 12 additions & 0 deletions Domain/Users/ValueObjects/UserId.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace Domain;

public record UserId
{
public Guid Value { get; private set; }

private UserId(Guid value) =>
Value = value;

public static UserId Create(Guid value) =>
new(value);
}
12 changes: 12 additions & 0 deletions Domain/Users/ValueObjects/UserMail.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace Domain;

public record UserMail
{
public string Value { get; private set; }

private UserMail(string value) =>
Value = value;

public static UserMail Create(string value) =>
new(value);
}
4 changes: 2 additions & 2 deletions ExpenseTracker.sln
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@


Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.6.33829.357
Expand Down Expand Up @@ -26,7 +26,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
docker-compose.yaml = docker-compose.yaml
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Architecture", "Architecture\Architecture.csproj", "{BE569021-A074-4DD6-BD8E-93B2B0B92A8C}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Architecture", "Architecture\Architecture.csproj", "{BE569021-A074-4DD6-BD8E-93B2B0B92A8C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down
43 changes: 43 additions & 0 deletions Infrastructure/Authentication/IdentityService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Application;
using Domain;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;

namespace Infrastructure;

public class IdentityService : IIdentityService
{
private readonly JwtOptions _options;

public IdentityService(IOptions<JwtOptions> options)
{
_options = options.Value;
}

public async Task<string> GenerateToken(User user)

Check warning on line 20 in Infrastructure/Authentication/IdentityService.cs

View workflow job for this annotation

GitHub Actions / Build project and run Architectural and Unit testing

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
{
var claims = new Claim[]
{
new Claim(JwtRegisteredClaimNames.Sub, user.Id.Value.ToString()),
new Claim(JwtRegisteredClaimNames.Email, user.Mail.Value)
};

var credentials = new SigningCredentials(
new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(_options.SecretKey)),
SecurityAlgorithms.HmacSha256);

var token = new JwtSecurityToken(
_options.Issuer,
_options.Audience,
claims, null,
DateTime.UtcNow.AddDays(1),
credentials);

return new JwtSecurityTokenHandler()
.WriteToken(token);
}
}
31 changes: 31 additions & 0 deletions Infrastructure/Authentication/Options/JwtBearerOptionsSetup.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System.Text;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;

namespace Infrastructure;

public class JwtBearerOptionsSetup : IConfigureOptions<JwtBearerOptions>
{
private readonly JwtOptions _options;

public JwtBearerOptionsSetup(IOptions<JwtOptions> options)
{
_options = options.Value;
}

public void Configure(JwtBearerOptions options)
{
options.TokenValidationParameters = new()
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = _options.Issuer,
ValidAudience = _options.Audience,
IssuerSigningKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(_options.SecretKey))
};
}
}
10 changes: 10 additions & 0 deletions Infrastructure/Authentication/Options/JwtOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace Infrastructure;

public class JwtOptions
{
public string Issuer { get; init; }

Check warning on line 5 in Infrastructure/Authentication/Options/JwtOptions.cs

View workflow job for this annotation

GitHub Actions / Build project and run Architectural and Unit testing

Non-nullable property 'Issuer' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

public string Audience { get; init; }

Check warning on line 7 in Infrastructure/Authentication/Options/JwtOptions.cs

View workflow job for this annotation

GitHub Actions / Build project and run Architectural and Unit testing

Non-nullable property 'Audience' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

public string SecretKey { get; init; }

Check warning on line 9 in Infrastructure/Authentication/Options/JwtOptions.cs

View workflow job for this annotation

GitHub Actions / Build project and run Architectural and Unit testing

Non-nullable property 'SecretKey' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
}
21 changes: 21 additions & 0 deletions Infrastructure/Authentication/Options/JwtOptionsSetup.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;

namespace Infrastructure;

public class JwtOptionsSetup : IConfigureOptions<JwtOptions>
{
private readonly IConfiguration _configuration;

private const string SectionName = nameof(JwtOptions);

public JwtOptionsSetup(IConfiguration configuration)
{
_configuration = configuration;
}

public void Configure(JwtOptions options)
{
_configuration.GetSection(SectionName).Bind(options);
}
}
11 changes: 9 additions & 2 deletions Infrastructure/DependencyInjection.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using Microsoft.Extensions.Configuration;
using Application;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System.Reflection;

Expand All @@ -8,8 +10,13 @@ public static class DependencyInjection
{
public static readonly Assembly Assembly = typeof(DependencyInjection).Assembly;

public static IServiceCollection AddInfrastructure(this IServiceCollection services, IConfiguration configuration)
public static IServiceCollection AddInfrastructure(this IServiceCollection services)
{
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer();

services.AddScoped<IIdentityService, IdentityService>();

return services;
}
}
9 changes: 5 additions & 4 deletions Infrastructure/Infrastructure.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@
<ProjectReference Include="..\Domain\Domain.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.0-rc.2.23480.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Abstractions" Version="8.0.0-rc.2.23480.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="8.0.0-rc.2.23479.6" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0-rc.2.23479.6" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Abstractions" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>
</Project>
6 changes: 4 additions & 2 deletions Persistance/DependencyInjection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@
using Persistance.Budgets;
using Domain.Expenses;
using Domain.Budgets;
using Domain;

namespace Persistance;
public static class DependencyInjection
{
public static readonly Assembly Assembly = typeof(DependencyInjection).Assembly;
public static IServiceCollection AddPersistance(this IServiceCollection services, IConfiguration configuration)
{
public static IServiceCollection AddPersistance(this IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>((serviceProvider, dbContextBuilder) =>
{
var databaseOptions = serviceProvider.GetService<IOptions<DatabaseOptions>>()!.Value;
Expand Down Expand Up @@ -57,6 +58,7 @@ public static IServiceCollection AddPersistance(this IServiceCollection services

services.AddScoped<IExpenseRepository, ExpenseRepository>();
services.AddScoped<IBudgetRepository, BudgetRepository>();
services.AddScoped<IUserRepository, UserRepository>();

services.AddQuartzHostedService();

Expand Down
Loading

0 comments on commit 1140e93

Please sign in to comment.