diff --git a/Directory.Build.props b/Directory.Build.props
index 2fc3dd9..b4b2f3d 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -1,7 +1,7 @@
- 2.2.0
+ 2.3.0
Tudor Stanciu
STA
Tuitio
diff --git a/ReleaseNotes.xml b/ReleaseNotes.xml
index c7a8b0c..77af9bd 100644
--- a/ReleaseNotes.xml
+++ b/ReleaseNotes.xml
@@ -53,11 +53,11 @@
2.0.0
◾ Tuitio rebranding
- ◾ .NET 6 upgrade
- ◾ Nuget packages upgrade
+ ◾ .NET 6 upgrade
+ ◾ Nuget packages upgrade
◾ Added Seq logging
◾ Refactoring and code cleanup
- ◾ Added README.md file
+ ◾ Added README.md file
@@ -75,4 +75,14 @@
◾ Added some tests
+
+ 2.3.0
+ 2023-03-27 19:20
+
+ Added "user-info" method in API
+ ◾ The "user-info" method returns the data of the authenticated user.
+ ◾ Added http context accessor and authentication handler
+ ◾ Added user contact options
+
+
\ No newline at end of file
diff --git a/dependencies.props b/dependencies.props
index 4cafce3..db91843 100644
--- a/dependencies.props
+++ b/dependencies.props
@@ -9,7 +9,7 @@
9.0.0
6.0.1
13.0.1
- 1.0.6
+ 1.0.7
1.2.0
1.0.0
diff --git a/src/Tuitio.Application/Abstractions/IHttpContextService.cs b/src/Tuitio.Application/Abstractions/IHttpContextService.cs
new file mode 100644
index 0000000..bfbcacd
--- /dev/null
+++ b/src/Tuitio.Application/Abstractions/IHttpContextService.cs
@@ -0,0 +1,7 @@
+namespace Tuitio.Application.Abstractions
+{
+ public interface IHttpContextService
+ {
+ int GetUserId();
+ }
+}
diff --git a/src/Tuitio.Application/Mappings/MappingProfile.cs b/src/Tuitio.Application/Mappings/MappingProfile.cs
index d1dfbf0..9b031f5 100644
--- a/src/Tuitio.Application/Mappings/MappingProfile.cs
+++ b/src/Tuitio.Application/Mappings/MappingProfile.cs
@@ -5,6 +5,7 @@ using Tuitio.Domain.Entities;
using System.Collections.Generic;
using dto = Tuitio.PublishedLanguage.Dto;
using models = Tuitio.Domain.Models;
+using Tuitio.Application.Queries;
namespace Tuitio.Application.Mappings
{
@@ -13,6 +14,14 @@ namespace Tuitio.Application.Mappings
public MappingProfile()
{
CreateMap();
+ CreateMap()
+ .ForMember(z => z.Claims, src => src.MapFrom(z => ComposeClaims(z.Claims)));
+
+ CreateMap()
+ .ForMember(z => z.Id, src => src.MapFrom(z => z.ContactOptionId))
+ .ForMember(z => z.ContactTypeCode, src => src.MapFrom(z => z.ContactType.ContactTypeCode))
+ .ForMember(z => z.ContactTypeName, src => src.MapFrom(z => z.ContactType.ContactTypeName));
+
CreateMap()
.ForMember(z => z.Claims, src => src.MapFrom(z => ComposeClaims(z.Claims)));
diff --git a/src/Tuitio.Application/Queries/GetUserInfo.cs b/src/Tuitio.Application/Queries/GetUserInfo.cs
new file mode 100644
index 0000000..89d1cfb
--- /dev/null
+++ b/src/Tuitio.Application/Queries/GetUserInfo.cs
@@ -0,0 +1,64 @@
+// Copyright (c) 2020 Tudor Stanciu
+
+using AutoMapper;
+using MediatR;
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using Tuitio.Application.Abstractions;
+using Tuitio.Domain.Repositories;
+
+namespace Tuitio.Application.Queries
+{
+ public class GetUserInfo
+ {
+ public class Query : IRequest { }
+
+ public record Model
+ {
+ public int UserId { get; set; }
+ public string UserName { get; set; }
+ public string FirstName { get; set; }
+ public string LastName { get; set; }
+ public string Email { get; set; }
+ public string ProfilePictureUrl { get; set; }
+ public string SecurityStamp { get; set; }
+ public DateTime CreationDate { get; set; }
+ public int? FailedLoginAttempts { get; set; }
+ public DateTime? LastLoginDate { get; set; }
+ public Dictionary Claims { get; init; }
+ public ContactOption[] ContactOptions { get; set; }
+ }
+
+ public record ContactOption
+ {
+ public int Id { get; set; }
+ public string ContactTypeCode { get; set; }
+ public string ContactTypeName { get; set; }
+ public string ContactValue { get; set; }
+ }
+
+ public class QueryHandler : IRequestHandler
+ {
+ private readonly IUserRepository _userRepository;
+ private readonly IHttpContextService _httpContextService;
+ private readonly IMapper _mapper;
+
+ public QueryHandler(IUserRepository userRepository, IHttpContextService httpContextService, IMapper mapper)
+ {
+ _userRepository=userRepository;
+ _httpContextService=httpContextService;
+ _mapper=mapper;
+ }
+
+ public async Task Handle(Query request, CancellationToken cancellationToken)
+ {
+ var userId = _httpContextService.GetUserId();
+ var user = await _userRepository.GetFullUser(userId);
+ var info = _mapper.Map(user);
+ return info;
+ }
+ }
+ }
+}
diff --git a/src/Tuitio.Domain.Data/DbContexts/TuitioDbContext.cs b/src/Tuitio.Domain.Data/DbContexts/TuitioDbContext.cs
index 497966b..26b4da0 100644
--- a/src/Tuitio.Domain.Data/DbContexts/TuitioDbContext.cs
+++ b/src/Tuitio.Domain.Data/DbContexts/TuitioDbContext.cs
@@ -27,6 +27,8 @@ namespace Tuitio.Domain.Data.DbContexts
modelBuilder.ApplyConfiguration(new AppUserConfiguration());
modelBuilder.ApplyConfiguration(new UserClaimConfiguration());
modelBuilder.ApplyConfiguration(new UserTokenConfiguration());
+ modelBuilder.ApplyConfiguration(new ContactTypeConfiguration());
+ modelBuilder.ApplyConfiguration(new ContactOptionConfiguration());
}
}
}
diff --git a/src/Tuitio.Domain.Data/EntityTypeConfiguration/AppUserConfiguration.cs b/src/Tuitio.Domain.Data/EntityTypeConfiguration/AppUserConfiguration.cs
index 95aaf93..771d0d0 100644
--- a/src/Tuitio.Domain.Data/EntityTypeConfiguration/AppUserConfiguration.cs
+++ b/src/Tuitio.Domain.Data/EntityTypeConfiguration/AppUserConfiguration.cs
@@ -14,6 +14,7 @@ namespace Tuitio.Domain.Data.EntityTypeConfiguration
builder.Property(z => z.UserId).ValueGeneratedOnAdd();
builder.HasOne(z => z.Status).WithMany().HasForeignKey(z => z.StatusId);
builder.HasMany(z => z.Claims).WithOne().HasForeignKey(z => z.UserId);
+ builder.HasMany(z => z.ContactOptions).WithOne().HasForeignKey(z => z.UserId);
}
}
}
diff --git a/src/Tuitio.Domain.Data/EntityTypeConfiguration/ContactOptionConfiguration.cs b/src/Tuitio.Domain.Data/EntityTypeConfiguration/ContactOptionConfiguration.cs
new file mode 100644
index 0000000..e934b2a
--- /dev/null
+++ b/src/Tuitio.Domain.Data/EntityTypeConfiguration/ContactOptionConfiguration.cs
@@ -0,0 +1,18 @@
+// Copyright (c) 2020 Tudor Stanciu
+
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+using Tuitio.Domain.Entities;
+
+namespace Tuitio.Domain.Data.EntityTypeConfiguration
+{
+ class ContactOptionConfiguration : IEntityTypeConfiguration
+ {
+ public void Configure(EntityTypeBuilder builder)
+ {
+ builder.ToTable("ContactOption").HasKey(key => key.ContactOptionId);
+ builder.Property(z => z.ContactOptionId).ValueGeneratedOnAdd();
+ builder.HasOne(z => z.ContactType).WithMany().HasForeignKey(z => z.ContactTypeId);
+ }
+ }
+}
diff --git a/src/Tuitio.Domain.Data/EntityTypeConfiguration/ContactTypeConfiguration.cs b/src/Tuitio.Domain.Data/EntityTypeConfiguration/ContactTypeConfiguration.cs
new file mode 100644
index 0000000..e92e4d6
--- /dev/null
+++ b/src/Tuitio.Domain.Data/EntityTypeConfiguration/ContactTypeConfiguration.cs
@@ -0,0 +1,17 @@
+// Copyright (c) 2020 Tudor Stanciu
+
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+using Tuitio.Domain.Entities;
+
+namespace Tuitio.Domain.Data.EntityTypeConfiguration
+{
+ class ContactTypeConfiguration : IEntityTypeConfiguration
+ {
+ public void Configure(EntityTypeBuilder builder)
+ {
+ builder.ToTable("ContactType").HasKey(z => z.ContactTypeId);
+ builder.Property(z => z.ContactTypeId).ValueGeneratedOnAdd();
+ }
+ }
+}
diff --git a/src/Tuitio.Domain.Data/Repositories/UserRepository.cs b/src/Tuitio.Domain.Data/Repositories/UserRepository.cs
index e11b6f6..f894100 100644
--- a/src/Tuitio.Domain.Data/Repositories/UserRepository.cs
+++ b/src/Tuitio.Domain.Data/Repositories/UserRepository.cs
@@ -28,6 +28,15 @@ namespace Tuitio.Domain.Data.Repositories
.FirstOrDefaultAsync(z => z.UserName == userName && z.Password == password);
}
+ public Task GetFullUser(int userId)
+ {
+ return _dbContext.Users
+ .Include(z => z.Status)
+ .Include(z => z.Claims)
+ .Include(z => z.ContactOptions).ThenInclude(z => z.ContactType)
+ .FirstOrDefaultAsync(z => z.UserId == userId);
+ }
+
public async Task UpdateUserAfterLogin(AppUser user, Token token, string tokenRaw)
{
var userToken = new UserToken()
diff --git a/src/Tuitio.Domain.Data/Scripts/2.3.0/01.ContactType table.sql b/src/Tuitio.Domain.Data/Scripts/2.3.0/01.ContactType table.sql
new file mode 100644
index 0000000..0172d6d
--- /dev/null
+++ b/src/Tuitio.Domain.Data/Scripts/2.3.0/01.ContactType table.sql
@@ -0,0 +1,24 @@
+if not exists (select top 1 1 from sys.objects where name = 'ContactType' and type = 'U')
+begin
+ create table ContactType
+ (
+ ContactTypeId int identity(1, 1) constraint PK_ContactType primary key,
+ ContactTypeCode varchar(30) not null,
+ ContactTypeName varchar(50) not null
+ )
+end
+
+if not exists (select top 1 1 from ContactType)
+begin
+ insert into ContactType(ContactTypeCode, ContactTypeName)
+ values ('EMAIL', 'Email'),
+ ('PHONE', 'Phone'),
+ ('WEBSITE', 'Website'),
+ ('LINKEDIN', 'LinkedIn'),
+ ('GITHUB', 'GitHub'),
+ ('GITEA', 'Gitea'),
+ ('PORTFOLIO', 'Portfolio'),
+ ('CURRICULUM_VITAE', 'Curriculum vitae'),
+ ('BLOG', 'Blog'),
+ ('REDDIT', 'Reddit')
+end
\ No newline at end of file
diff --git a/src/Tuitio.Domain.Data/Scripts/2.3.0/02.ContactOption table.sql b/src/Tuitio.Domain.Data/Scripts/2.3.0/02.ContactOption table.sql
new file mode 100644
index 0000000..9e0c394
--- /dev/null
+++ b/src/Tuitio.Domain.Data/Scripts/2.3.0/02.ContactOption table.sql
@@ -0,0 +1,10 @@
+if not exists (select top 1 1 from sys.objects where name = 'ContactOption' and type = 'U')
+begin
+ create table ContactOption
+ (
+ ContactOptionId int identity(1, 1) constraint PK_ContactOption primary key,
+ UserId int constraint FK_ContactOption_AppUser foreign key references AppUser(UserId),
+ ContactTypeId int constraint FK_ContactOption_ContactType foreign key references ContactType(ContactTypeId),
+ ContactValue varchar(150) not null
+ )
+end
\ No newline at end of file
diff --git a/src/Tuitio.Domain.Data/Tuitio.Domain.Data.csproj b/src/Tuitio.Domain.Data/Tuitio.Domain.Data.csproj
index edd04a6..cd5c1bf 100644
--- a/src/Tuitio.Domain.Data/Tuitio.Domain.Data.csproj
+++ b/src/Tuitio.Domain.Data/Tuitio.Domain.Data.csproj
@@ -28,6 +28,12 @@
PreserveNewest
+
+ PreserveNewest
+
+
+ PreserveNewest
+
diff --git a/src/Tuitio.Domain/Entities/AppUser.cs b/src/Tuitio.Domain/Entities/AppUser.cs
index f9289d2..f7933bf 100644
--- a/src/Tuitio.Domain/Entities/AppUser.cs
+++ b/src/Tuitio.Domain/Entities/AppUser.cs
@@ -22,5 +22,6 @@ namespace Tuitio.Domain.Entities
public DateTime? PasswordChangeDate { get; set; }
public UserStatus Status { get; set; }
public ICollection Claims { get; set; }
+ public ICollection ContactOptions { get; set; }
}
}
diff --git a/src/Tuitio.Domain/Entities/ContactInfo.cs b/src/Tuitio.Domain/Entities/ContactInfo.cs
new file mode 100644
index 0000000..9348217
--- /dev/null
+++ b/src/Tuitio.Domain/Entities/ContactInfo.cs
@@ -0,0 +1,13 @@
+// Copyright (c) 2020 Tudor Stanciu
+
+namespace Tuitio.Domain.Entities
+{
+ public class ContactOption
+ {
+ public int ContactOptionId { get; set; }
+ public int UserId { get; set; }
+ public int ContactTypeId { get; set; }
+ public string ContactValue { get; set; }
+ public ContactType ContactType { get; set; }
+ }
+}
diff --git a/src/Tuitio.Domain/Entities/ContactType.cs b/src/Tuitio.Domain/Entities/ContactType.cs
new file mode 100644
index 0000000..98fcf1c
--- /dev/null
+++ b/src/Tuitio.Domain/Entities/ContactType.cs
@@ -0,0 +1,11 @@
+// Copyright (c) 2020 Tudor Stanciu
+
+namespace Tuitio.Domain.Entities
+{
+ public class ContactType
+ {
+ public int ContactTypeId { get; set; }
+ public string ContactTypeCode { get; set; }
+ public string ContactTypeName { get; set; }
+ }
+}
diff --git a/src/Tuitio.Domain/Models/Token.cs b/src/Tuitio.Domain/Models/Token.cs
index 9877562..f2621d3 100644
--- a/src/Tuitio.Domain/Models/Token.cs
+++ b/src/Tuitio.Domain/Models/Token.cs
@@ -13,7 +13,6 @@ namespace Tuitio.Domain.Models
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
- public string ProfilePictureUrl { get; set; }
public string SecurityStamp { get; set; }
public string LockStamp { get; set; }
public DateTime CreatedAt { get; set; }
diff --git a/src/Tuitio.Domain/Repositories/IUserRepository.cs b/src/Tuitio.Domain/Repositories/IUserRepository.cs
index 158f629..4122059 100644
--- a/src/Tuitio.Domain/Repositories/IUserRepository.cs
+++ b/src/Tuitio.Domain/Repositories/IUserRepository.cs
@@ -10,6 +10,7 @@ namespace Tuitio.Domain.Repositories
public interface IUserRepository
{
Task GetUser(string userName, string password);
+ Task GetFullUser(int userId);
Task UpdateUserAfterLogin(AppUser user, Token token, string tokenRaw);
Task GetActiveTokens();
Task RemoveToken(Guid tokenId);
diff --git a/src/Tuitio.PublishedLanguage/Dto/ResultRecords.cs b/src/Tuitio.PublishedLanguage/Dto/ResultRecords.cs
index 21bcbf2..1cdf55d 100644
--- a/src/Tuitio.PublishedLanguage/Dto/ResultRecords.cs
+++ b/src/Tuitio.PublishedLanguage/Dto/ResultRecords.cs
@@ -15,7 +15,6 @@ namespace Tuitio.PublishedLanguage.Dto
public string FirstName { get; init; }
public string LastName { get; init; }
public string Email { get; init; }
- public string ProfilePictureUrl { get; init; }
public string SecurityStamp { get; init; }
public string LockStamp { get; init; }
public DateTime CreatedAt { get; init; }
diff --git a/src/Tuitio/Authentication/AuthenticationExtensions.cs b/src/Tuitio/Authentication/AuthenticationExtensions.cs
new file mode 100644
index 0000000..66eabb1
--- /dev/null
+++ b/src/Tuitio/Authentication/AuthenticationExtensions.cs
@@ -0,0 +1,18 @@
+using Microsoft.AspNetCore.Authentication;
+using Microsoft.Extensions.DependencyInjection;
+using Tuitio.Application.Abstractions;
+
+namespace Tuitio.Authentication
+{
+ internal static class AuthenticationExtensions
+ {
+ public static IServiceCollection AddLocalAuthentication(this IServiceCollection services)
+ {
+ var scheme = "TuitioAuthentication";
+ services.AddAuthentication(scheme)
+ .AddScheme(scheme, null);
+ services.AddScoped();
+ return services;
+ }
+ }
+}
diff --git a/src/Tuitio/Authentication/AuthenticationHandler.cs b/src/Tuitio/Authentication/AuthenticationHandler.cs
new file mode 100644
index 0000000..8c1a0da
--- /dev/null
+++ b/src/Tuitio/Authentication/AuthenticationHandler.cs
@@ -0,0 +1,91 @@
+using Microsoft.AspNetCore.Authentication;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.Http.Headers;
+using System.Security.Claims;
+using System.Text.Encodings.Web;
+using System.Threading.Tasks;
+using Tuitio.Application.Services.Abstractions;
+using Tuitio.Domain.Models;
+
+namespace Tuitio.Authentication
+{
+ public class AuthenticationHandler : AuthenticationHandler
+ {
+ private readonly IUserService _userService;
+ private readonly ILogger _logger;
+
+ public AuthenticationHandler(IOptionsMonitor options, ILoggerFactory loggerFactory, UrlEncoder encoder, ISystemClock clock, IUserService userService, ILogger logger) : base(options, loggerFactory, encoder, clock)
+ {
+ _userService=userService;
+ _logger=logger;
+ }
+
+ protected override async Task HandleAuthenticateAsync()
+ {
+ var token = GetAuthorizationToken();
+ if (token == null)
+ return AuthenticateResult.Fail("AUTHORIZATION_HEADER_IS_MISSING");
+
+ var result = await Task.Run(() => _userService.Authorize(token));
+ if (result == null)
+ return AuthenticateResult.Fail("UNAUTHORIZED");
+
+ var ticket = GetAuthenticationTicket(result);
+ return AuthenticateResult.Success(ticket);
+ }
+
+ private string GetAuthorizationToken()
+ {
+ if (Request.Headers.ContainsKey("Authorization"))
+ {
+ var authorizationHeader = AuthenticationHeaderValue.Parse(Request.Headers["Authorization"]);
+ var token = authorizationHeader.Parameter;
+ return token;
+ }
+
+ return null;
+ }
+
+ private AuthenticationTicket GetAuthenticationTicket(Token result)
+ {
+ var claimCollection = new Dictionary()
+ {
+ { ClaimTypes.NameIdentifier, result.UserId.ToString() },
+ { ClaimTypes.Name, result.UserName },
+ };
+
+ if (result.FirstName != null)
+ claimCollection.Add(ClaimTypes.GivenName, result.FirstName);
+
+ if (result.LastName != null)
+ claimCollection.Add(ClaimTypes.Surname, result.FirstName);
+
+ if (result.Email != null)
+ claimCollection.Add(ClaimTypes.Email, result.Email);
+
+ if (result.Claims != null && result.Claims.Any())
+ {
+ foreach (var claim in result.Claims)
+ {
+ if (claimCollection.ContainsKey(claim.Key))
+ {
+ _logger.LogWarning($"There is already a claim with key {claim.Key} in the collection. The combination {claim.Key}:{claim.Value} will be ignored.");
+ continue;
+ }
+
+ claimCollection.Add(claim.Key, claim.Value);
+ }
+ }
+
+ var claims = claimCollection.Select(z => new Claim(z.Key, z.Value)).ToArray();
+ var identity = new ClaimsIdentity(claims, Scheme.Name);
+ var principal = new ClaimsPrincipal(identity);
+ var ticket = new AuthenticationTicket(principal, Scheme.Name);
+
+ return ticket;
+ }
+ }
+}
diff --git a/src/Tuitio/Authentication/HttpContextService.cs b/src/Tuitio/Authentication/HttpContextService.cs
new file mode 100644
index 0000000..682c7b5
--- /dev/null
+++ b/src/Tuitio/Authentication/HttpContextService.cs
@@ -0,0 +1,31 @@
+using Microsoft.AspNetCore.Http;
+using System.Linq;
+using System;
+using Tuitio.Application.Abstractions;
+using System.Security.Claims;
+
+namespace Tuitio.Authentication
+{
+ public class HttpContextService : IHttpContextService
+ {
+ private readonly IHttpContextAccessor _httpAccessor;
+
+ public HttpContextService(IHttpContextAccessor httpAccessor)
+ {
+ _httpAccessor=httpAccessor;
+ }
+
+ public int GetUserId()
+ {
+ var userIdString = _httpAccessor.HttpContext.User?.Claims.FirstOrDefault(z => z.Type == ClaimTypes.NameIdentifier)?.Value;
+
+ if (string.IsNullOrEmpty(userIdString))
+ throw new Exception("User id could not be retrieved from claims.");
+
+ if (!int.TryParse(userIdString, out int userId))
+ throw new Exception("User id is not a valid integer.");
+
+ return userId;
+ }
+ }
+}
diff --git a/src/Tuitio/Controllers/ConnectController.cs b/src/Tuitio/Controllers/ConnectController.cs
index e94b151..31d1d50 100644
--- a/src/Tuitio/Controllers/ConnectController.cs
+++ b/src/Tuitio/Controllers/ConnectController.cs
@@ -1,12 +1,15 @@
// Copyright (c) 2020 Tudor Stanciu
using MediatR;
+using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
using Tuitio.Application.CommandHandlers;
+using Tuitio.Application.Queries;
namespace Tuitio.Api.Controllers
{
+ [Authorize]
[ApiController]
[Route("connect")]
public class ConnectController : ControllerBase
@@ -18,6 +21,7 @@ namespace Tuitio.Api.Controllers
_mediator = mediator;
}
+ [AllowAnonymous]
[HttpPost("authorize")]
public async Task AuthorizeToken([FromQuery] string token)
{
@@ -25,5 +29,13 @@ namespace Tuitio.Api.Controllers
var result = await _mediator.Send(command);
return Ok(result);
}
+
+ [HttpGet("user-info")]
+ public async Task GetUserInfo()
+ {
+ var command = new GetUserInfo.Query();
+ var result = await _mediator.Send(command);
+ return Ok(result);
+ }
}
}
diff --git a/src/Tuitio/Extensions/StartupExtensions.cs b/src/Tuitio/Extensions/StartupExtensions.cs
index 03e9e76..b2c57f8 100644
--- a/src/Tuitio/Extensions/StartupExtensions.cs
+++ b/src/Tuitio/Extensions/StartupExtensions.cs
@@ -11,6 +11,7 @@ using Netmash.Infrastructure.DatabaseMigration;
using Netmash.Infrastructure.DatabaseMigration.Constants;
using Tuitio.Application;
using Tuitio.Application.Services.Abstractions;
+using Tuitio.Authentication;
using Tuitio.Domain.Data;
namespace Tuitio.Extensions
@@ -20,6 +21,8 @@ namespace Tuitio.Extensions
public static void ConfigureServices(this IServiceCollection services, IConfiguration configuration)
{
services.AddControllers();
+ services.AddLocalAuthentication();
+ services.AddHttpContextAccessor();
// MediatR
services.AddMediatR(typeof(Application.CommandHandlers.AccountLoginHandler).Assembly);
@@ -30,7 +33,7 @@ namespace Tuitio.Extensions
services.AddAutoMapper(typeof(Application.Mappings.MappingProfile).Assembly);
// Swagger
- services.AddSwagger("Tuitio API", AuthorizationType.None);
+ services.AddSwagger("Tuitio API", AuthorizationType.Tuitio);
// Data access
services.AddMigration(DatabaseType.SQLServer, MetadataLocation.Database);
@@ -47,6 +50,7 @@ namespace Tuitio.Extensions
app.UseCors(z => z.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
app.UseRouting();
+ app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{