Tuitio refactoring

master
Tudor Stanciu 2023-03-07 19:36:12 +02:00
parent e5854ef76b
commit 747b91898d
26 changed files with 117 additions and 104 deletions

View File

@ -17,7 +17,7 @@
<Note> <Note>
<Version>1.0.1</Version> <Version>1.0.1</Version>
<Content> <Content>
Hard changes in token structure. Now the token format is base64 and contains a json with all user data like username, first name, last name, profile picture url, email address and a list of claims that can be configured from the database for each user independently. Big changes in token structure. Now the token format is base64 and contains a json with all user data like username, first name, last name, profile picture url, email address and a list of claims that can be configured from the database for each user independently.
◾ The generation and validation mechanism for the token has been rewritten to meet the new token structure. ◾ The generation and validation mechanism for the token has been rewritten to meet the new token structure.
◾ The complexity of user information has grown a lot. All users have now besides the data from token other information such as statuses, failed login attempts, last login date, password change date and security stamp. ◾ The complexity of user information has grown a lot. All users have now besides the data from token other information such as statuses, failed login attempts, last login date, password change date and security stamp.
◾ All tokens are persisted in the database and the active ones are reload at a server failure or in case of a restart. ◾ All tokens are persisted in the database and the active ones are reload at a server failure or in case of a restart.
@ -60,4 +60,12 @@
◾ Added README.md file ◾ Added README.md file
</Content> </Content>
</Note> </Note>
<Note>
<Version>2.1.0</Version>
<Content>
◾ Tuitio refactoring
◾ Added account logout method
◾ Tuitio performance optimizations
</Content>
</Note>
</ReleaseNotes> </ReleaseNotes>

View File

@ -4,7 +4,7 @@ using MediatR;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Tuitio.Application.Services; using Tuitio.Application.Services.Abstractions;
using Tuitio.PublishedLanguage.Constants; using Tuitio.PublishedLanguage.Constants;
using Tuitio.PublishedLanguage.Dto; using Tuitio.PublishedLanguage.Dto;
@ -30,15 +30,13 @@ namespace Tuitio.Application.CommandHandlers
var loginResult = await _userService.Login(command.UserName, command.Password); var loginResult = await _userService.Login(command.UserName, command.Password);
if (loginResult == null) if (loginResult == null)
{ {
_logger.LogDebug($"Authentication failed for user '{command.UserName}'."); _logger.LogDebug($"Login failed for user '{command.UserName}'.");
return Envelope<AccountLoginResult>.Error(EnvelopeStatus.BAD_CREDENTIALS); return Envelope<AccountLoginResult>.Error(EnvelopeStatus.BAD_CREDENTIALS);
} }
_logger.LogDebug($"Authentication succeeded for user '{command.UserName}'."); _logger.LogDebug($"Login succeeded for user '{command.UserName}'.");
var token = new Token(loginResult.Raw, loginResult.Token.ExpiresIn); var result = new AccountLoginResult(loginResult.Raw, loginResult.Token.ExpiresIn);
var result = new AccountLoginResult(token);
return Envelope<AccountLoginResult>.Success(result); return Envelope<AccountLoginResult>.Success(result);
} }
} }

View File

@ -5,7 +5,8 @@ using MediatR;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Tuitio.Application.Services; using Tuitio.Application.Services.Abstractions;
using Tuitio.PublishedLanguage.Constants;
using Tuitio.PublishedLanguage.Dto; using Tuitio.PublishedLanguage.Dto;
namespace Tuitio.Application.CommandHandlers namespace Tuitio.Application.CommandHandlers
@ -30,6 +31,12 @@ namespace Tuitio.Application.CommandHandlers
public async Task<Envelope<AccountLogoutResult>> Handle(Command command, CancellationToken cancellationToken) public async Task<Envelope<AccountLogoutResult>> Handle(Command command, CancellationToken cancellationToken)
{ {
var logoutResult = await _userService.Logout(command.Token); var logoutResult = await _userService.Logout(command.Token);
if (logoutResult == null)
{
_logger.LogDebug($"Logout failed for token '{command.Token}'.");
return Envelope<AccountLogoutResult>.Error(EnvelopeStatus.UNAUTHENTICATED);
}
_logger.LogDebug($"Logout succeeded for user '{logoutResult.UserName}'."); _logger.LogDebug($"Logout succeeded for user '{logoutResult.UserName}'.");
var result = _mapper.Map<AccountLogoutResult>(logoutResult); var result = _mapper.Map<AccountLogoutResult>(logoutResult);

View File

@ -1,46 +1,46 @@
// Copyright (c) 2020 Tudor Stanciu // Copyright (c) 2020 Tudor Stanciu
using AutoMapper; using AutoMapper;
using Tuitio.Application.Services;
using Tuitio.PublishedLanguage.Dto;
using MediatR; using MediatR;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Tuitio.Application.Services.Abstractions;
using Tuitio.PublishedLanguage.Constants; using Tuitio.PublishedLanguage.Constants;
using Tuitio.PublishedLanguage.Dto;
namespace Tuitio.Application.CommandHandlers namespace Tuitio.Application.CommandHandlers
{ {
public class AuthorizeTokenHandler public class AuthorizationHandler
{ {
public record Command(string Token) : IRequest<Envelope<TokenAuthorizationResult>>; public record Command(string Token) : IRequest<Envelope<AuthorizationResult>>;
public class CommandHandler : IRequestHandler<Command, Envelope<TokenAuthorizationResult>> public class CommandHandler : IRequestHandler<Command, Envelope<AuthorizationResult>>
{ {
private readonly IUserService _userService; private readonly IUserService _userService;
private readonly IMapper _mapper; private readonly IMapper _mapper;
private readonly ILogger<AuthorizeTokenHandler> _logger; private readonly ILogger<AuthorizationHandler> _logger;
public CommandHandler(IUserService userService, IMapper mapper, ILogger<AuthorizeTokenHandler> logger) public CommandHandler(IUserService userService, IMapper mapper, ILogger<AuthorizationHandler> logger)
{ {
_userService = userService; _userService = userService;
_mapper = mapper; _mapper = mapper;
_logger = logger; _logger = logger;
} }
public Task<Envelope<TokenAuthorizationResult>> Handle(Command command, CancellationToken cancellationToken) public Task<Envelope<AuthorizationResult>> Handle(Command command, CancellationToken cancellationToken)
{ {
var token = _userService.Authorize(command.Token); var token = _userService.Authorize(command.Token);
if (token == null) if (token == null)
{ {
_logger.LogDebug($"Authorization failed for token '{command.Token}'."); _logger.LogDebug($"Authorization failed for token '{command.Token}'.");
var result = Envelope<TokenAuthorizationResult>.Error(EnvelopeStatus.UNAUTHORIZED); var result = Envelope<AuthorizationResult>.Error(EnvelopeStatus.UNAUTHORIZED);
return Task.FromResult(result); return Task.FromResult(result);
} }
_logger.LogDebug($"Authorization succeeded for token '{command.Token}'."); _logger.LogDebug($"Authorization succeeded for token '{command.Token}'.");
var authorizationResult = new TokenAuthorizationResult(_mapper.Map<TokenCore>(token)); var authorizationResult = _mapper.Map<AuthorizationResult>(token);
var envelope = Envelope<TokenAuthorizationResult>.Success(authorizationResult); var envelope = Envelope<AuthorizationResult>.Success(authorizationResult);
return Task.FromResult(envelope); return Task.FromResult(envelope);
} }
} }

View File

@ -1,10 +1,10 @@
// Copyright (c) 2020 Tudor Stanciu // Copyright (c) 2020 Tudor Stanciu
using Microsoft.Extensions.DependencyInjection;
using Tuitio.Application.Services; using Tuitio.Application.Services;
using Tuitio.Application.Services.Abstractions; using Tuitio.Application.Services.Abstractions;
using Tuitio.Application.Stores; using Tuitio.Application.Stores;
using Tuitio.Domain.Abstractions; using Tuitio.Domain.Abstractions;
using Microsoft.Extensions.DependencyInjection;
namespace Tuitio.Application namespace Tuitio.Application
{ {

View File

@ -12,7 +12,7 @@ namespace Tuitio.Application.Mappings
{ {
public MappingProfile() public MappingProfile()
{ {
CreateMap<models.Token, dto.TokenCore>(); CreateMap<models.Token, dto.AuthorizationResult>();
CreateMap<AppUser, models.Token>() CreateMap<AppUser, models.Token>()
.ForMember(z => z.Claims, src => src.MapFrom(z => ComposeClaims(z.Claims))); .ForMember(z => z.Claims, src => src.MapFrom(z => ComposeClaims(z.Claims)));

View File

@ -3,7 +3,7 @@
using Tuitio.Domain.Entities; using Tuitio.Domain.Entities;
using Tuitio.Domain.Models; using Tuitio.Domain.Models;
namespace Tuitio.Application.Services namespace Tuitio.Application.Services.Abstractions
{ {
internal interface ITokenService internal interface ITokenService
{ {

View File

@ -1,10 +1,10 @@
// Copyright (c) 2020 Tudor Stanciu // Copyright (c) 2020 Tudor Stanciu
using Tuitio.Domain.Models;
using System.Threading.Tasks; using System.Threading.Tasks;
using Tuitio.Domain.Models;
using Tuitio.Domain.Models.Account; using Tuitio.Domain.Models.Account;
namespace Tuitio.Application.Services namespace Tuitio.Application.Services.Abstractions
{ {
public interface IUserService public interface IUserService
{ {

View File

@ -5,6 +5,7 @@ using Newtonsoft.Json;
using System; using System;
using System.Text; using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using Tuitio.Application.Services.Abstractions;
using Tuitio.Application.Stores; using Tuitio.Application.Stores;
using Tuitio.Domain.Abstractions; using Tuitio.Domain.Abstractions;
using Tuitio.Domain.Entities; using Tuitio.Domain.Entities;

View File

@ -1,14 +1,14 @@
// Copyright (c) 2020 Tudor Stanciu // Copyright (c) 2020 Tudor Stanciu
using System;
using System.Threading.Tasks;
using Tuitio.Application.Services.Abstractions; using Tuitio.Application.Services.Abstractions;
using Tuitio.Application.Stores; using Tuitio.Application.Stores;
using Tuitio.Domain.Abstractions; using Tuitio.Domain.Abstractions;
using Tuitio.Domain.Entities; using Tuitio.Domain.Entities;
using Tuitio.Domain.Models; using Tuitio.Domain.Models;
using Tuitio.Domain.Repositories;
using System;
using System.Threading.Tasks;
using Tuitio.Domain.Models.Account; using Tuitio.Domain.Models.Account;
using Tuitio.Domain.Repositories;
namespace Tuitio.Application.Services namespace Tuitio.Application.Services
{ {
@ -33,6 +33,9 @@ namespace Tuitio.Application.Services
{ {
var passwordHash = _hashingService.HashSha256(password); var passwordHash = _hashingService.HashSha256(password);
var user = await _userRepository.GetUser(userName, passwordHash); var user = await _userRepository.GetUser(userName, passwordHash);
if (user == null)
return null;
var valid = ValidateUser(user); var valid = ValidateUser(user);
if (!valid) if (!valid)
return null; return null;
@ -41,8 +44,7 @@ namespace Tuitio.Application.Services
var raw = _tokenService.GenerateTokenRaw(token); var raw = _tokenService.GenerateTokenRaw(token);
_securityStore.Set(raw, token); _securityStore.Set(raw, token);
await _userRepository.UpdateUserAfterLogin(user, token, raw);
await _userRepository.UpdateUserAfterAuthentication(user, token, raw);
var result = new LoginResult(token, raw); var result = new LoginResult(token, raw);
return result; return result;

View File

@ -1,13 +1,13 @@
// Copyright (c) 2020 Tudor Stanciu // Copyright (c) 2020 Tudor Stanciu
using Tuitio.Domain.Data.DbContexts;
using Tuitio.Domain.Entities;
using Tuitio.Domain.Models;
using Tuitio.Domain.Repositories;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using System; using System;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Tuitio.Domain.Data.DbContexts;
using Tuitio.Domain.Entities;
using Tuitio.Domain.Models;
using Tuitio.Domain.Repositories;
namespace Tuitio.Domain.Data.Repositories namespace Tuitio.Domain.Data.Repositories
{ {
@ -28,7 +28,7 @@ namespace Tuitio.Domain.Data.Repositories
.FirstOrDefaultAsync(z => z.UserName == userName && z.Password == password); .FirstOrDefaultAsync(z => z.UserName == userName && z.Password == password);
} }
public async Task UpdateUserAfterAuthentication(AppUser user, Token token, string tokenRaw) public async Task UpdateUserAfterLogin(AppUser user, Token token, string tokenRaw)
{ {
var userToken = new UserToken() var userToken = new UserToken()
{ {
@ -40,23 +40,25 @@ namespace Tuitio.Domain.Data.Repositories
}; };
await _dbContext.AddAsync(userToken); await _dbContext.AddAsync(userToken);
user.LastLoginDate = DateTime.UtcNow; user.LastLoginDate = DateTime.UtcNow;
//asta nu trebuie
//_dbContext.Update(user);
await _dbContext.SaveChangesAsync(); await _dbContext.SaveChangesAsync();
} }
public Task<UserToken[]> GetActiveTokens() public async Task<UserToken[]> GetActiveTokens()
{ {
var currentDate = DateTime.UtcNow; var currentDate = DateTime.UtcNow;
// remove expired tokens
_dbContext.UserTokens.RemoveRange(_dbContext.UserTokens.Where(z => z.ValidUntil < currentDate));
await _dbContext.SaveChangesAsync();
// retrieve active tokens
var query = _dbContext.UserTokens var query = _dbContext.UserTokens
.Where(z => z.ValidFrom <= currentDate && z.ValidUntil >= currentDate); .Where(z => z.ValidFrom <= currentDate && z.ValidUntil >= currentDate);
// read all tokens, keep the valid ones and remove the expired ones. var tokens = await query.ToArrayAsync();
return query.ToArrayAsync(); return tokens;
} }
public Task RemoveToken(Guid tokenId) public Task RemoveToken(Guid tokenId)

View File

@ -10,7 +10,7 @@ namespace Tuitio.Domain.Repositories
public interface IUserRepository public interface IUserRepository
{ {
Task<AppUser> GetUser(string userName, string password); Task<AppUser> GetUser(string userName, string password);
Task UpdateUserAfterAuthentication(AppUser user, Token token, string tokenRaw); Task UpdateUserAfterLogin(AppUser user, Token token, string tokenRaw);
Task<UserToken[]> GetActiveTokens(); Task<UserToken[]> GetActiveTokens();
Task RemoveToken(Guid tokenId); Task RemoveToken(Guid tokenId);
} }

View File

@ -6,6 +6,7 @@ namespace Tuitio.PublishedLanguage.Constants
{ {
public const string public const string
BAD_CREDENTIALS = "BAD_CREDENTIALS", BAD_CREDENTIALS = "BAD_CREDENTIALS",
UNAUTHENTICATED = "UNAUTHENTICATED",
UNAUTHORIZED = "UNAUTHORIZED"; UNAUTHORIZED = "UNAUTHORIZED";
} }
} }

View File

@ -1,10 +1,25 @@
// Copyright (c) 2020 Tudor Stanciu // Copyright (c) 2020 Tudor Stanciu
using System; using System;
using System.Collections.Generic;
namespace Tuitio.PublishedLanguage.Dto namespace Tuitio.PublishedLanguage.Dto
{ {
public record AccountLoginResult(Token Token); public record AccountLoginResult(string Token, double ExpiresIn);
public record AccountLogoutResult(int UserId, string UserName, DateTime LogoutDate); public record AccountLogoutResult(int UserId, string UserName, DateTime LogoutDate);
public record TokenAuthorizationResult(TokenCore TokenCore); public class AuthorizationResult
{
public Guid TokenId { get; init; }
public int UserId { get; init; }
public string UserName { get; init; }
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; }
public double ExpiresIn { get; init; }
public Dictionary<string, string> Claims { get; init; }
}
} }

View File

@ -1,7 +0,0 @@
// Copyright (c) 2020 Tudor Stanciu
namespace Tuitio.PublishedLanguage.Dto
{
// move this in result
public record Token(string Raw, double ExpiresIn);
}

View File

@ -1,19 +0,0 @@
// Copyright (c) 2020 Tudor Stanciu
using System.Collections.Generic;
namespace Tuitio.PublishedLanguage.Dto
{
public class TokenCore
{
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 string LockStamp { get; set; }
public Dictionary<string, string> Claims { get; set; }
}
}

View File

@ -1,3 +1,7 @@
2.0.0 release [2023-01-31 02:17] 2.1.0 release [2023-03-07 22:17]
◾ Tuitio refactoring
◾ Added account logout method
2.0.0 release [2023-01-31 02:17]
◾ Tuitio rebranding ◾ Tuitio rebranding
◾ Initial release of Tuitio's published language package ◾ Initial release of Tuitio's published language package

View File

@ -7,7 +7,7 @@
<RepositoryUrl>https://lab.code-rove.com/gitea/tudor.stanciu/tuitio</RepositoryUrl> <RepositoryUrl>https://lab.code-rove.com/gitea/tudor.stanciu/tuitio</RepositoryUrl>
<RepositoryType>Git</RepositoryType> <RepositoryType>Git</RepositoryType>
<PackageReleaseNotes>$([System.IO.File]::ReadAllText("$(MSBuildProjectDirectory)/ReleaseNotes.txt"))</PackageReleaseNotes> <PackageReleaseNotes>$([System.IO.File]::ReadAllText("$(MSBuildProjectDirectory)/ReleaseNotes.txt"))</PackageReleaseNotes>
<Version>2.0.0</Version> <Version>2.1.0</Version>
<PackageIcon>logo.png</PackageIcon> <PackageIcon>logo.png</PackageIcon>
<PackageReadmeFile>README.md</PackageReadmeFile> <PackageReadmeFile>README.md</PackageReadmeFile>
<Company>Toodle HomeLab</Company> <Company>Toodle HomeLab</Company>

View File

@ -5,7 +5,8 @@ namespace Tuitio.Wrapper.Constants
internal struct ApiRoutes internal struct ApiRoutes
{ {
public const string public const string
Authentication = "account/login?UserName={0}&Password={1}", AccountLogin = "account/login?UserName={0}&Password={1}",
AccountLogout = "account/logout?Token={0}",
Authorization = "connect/authorize?Token={0}"; Authorization = "connect/authorize?Token={0}";
} }
} }

View File

@ -1,3 +1,7 @@
2.0.0 release [2023-01-31 02:17] 2.1.0 release [2023-03-07 22:17]
◾ Tuitio refactoring
◾ Added account logout method
2.0.0 release [2023-01-31 02:17]
◾ Tuitio rebranding ◾ Tuitio rebranding
◾ Initial release of Tuitio's API wrapper ◾ Initial release of Tuitio's API wrapper

View File

@ -1,13 +1,13 @@
// Copyright (c) 2020 Tudor Stanciu // Copyright (c) 2020 Tudor Stanciu
using Tuitio.PublishedLanguage.Dto;
using System.Threading.Tasks; using System.Threading.Tasks;
using Tuitio.PublishedLanguage.Dto;
namespace Tuitio.Wrapper.Services namespace Tuitio.Wrapper.Services
{ {
public interface ITuitioService public interface ITuitioService
{ {
Task<Token> Authenticate(string userName, string password); Task<AccountLoginResult> Login(string userName, string password);
Task<TokenAuthorizationResult> Authorize(string token); Task<AuthorizationResult> Authorize(string token);
} }
} }

View File

@ -1,13 +1,13 @@
// Copyright (c) 2020 Tudor Stanciu // Copyright (c) 2020 Tudor Stanciu
using Tuitio.PublishedLanguage.Dto;
using Tuitio.Wrapper.Constants;
using Tuitio.Wrapper.Models;
using Netmash.Extensions.Http; using Netmash.Extensions.Http;
using System; using System;
using System.Net.Http; using System.Net.Http;
using System.Net.Http.Headers; using System.Net.Http.Headers;
using System.Threading.Tasks; using System.Threading.Tasks;
using Tuitio.PublishedLanguage.Dto;
using Tuitio.Wrapper.Constants;
using Tuitio.Wrapper.Models;
namespace Tuitio.Wrapper.Services namespace Tuitio.Wrapper.Services
{ {
@ -24,17 +24,24 @@ namespace Tuitio.Wrapper.Services
_httpClient = httpClient; _httpClient = httpClient;
} }
public async Task<Token> Authenticate(string userName, string password) public async Task<AccountLoginResult> Login(string userName, string password)
{ {
var route = string.Format(ApiRoutes.Authentication, userName, password); var route = string.Format(ApiRoutes.AccountLogin, userName, password);
var result = await _httpClient.ExecutePostRequest<Token>(route); var result = await _httpClient.ExecutePostRequest<AccountLoginResult>(route);
return result; return result;
} }
public async Task<TokenAuthorizationResult> Authorize(string token) public async Task<AccountLogoutResult> Logout(string token)
{
var route = string.Format(ApiRoutes.AccountLogout, token);
var result = await _httpClient.ExecutePostRequest<AccountLogoutResult>(route);
return result;
}
public async Task<AuthorizationResult> Authorize(string token)
{ {
var route = string.Format(ApiRoutes.Authorization, token); var route = string.Format(ApiRoutes.Authorization, token);
var result = await _httpClient.ExecutePostRequest<TokenAuthorizationResult>(route); var result = await _httpClient.ExecutePostRequest<AuthorizationResult>(route);
return result; return result;
} }
} }

View File

@ -7,7 +7,7 @@
<RepositoryUrl>https://lab.code-rove.com/gitea/tudor.stanciu/tuitio</RepositoryUrl> <RepositoryUrl>https://lab.code-rove.com/gitea/tudor.stanciu/tuitio</RepositoryUrl>
<RepositoryType>Git</RepositoryType> <RepositoryType>Git</RepositoryType>
<PackageReleaseNotes>$([System.IO.File]::ReadAllText("$(MSBuildProjectDirectory)/ReleaseNotes.txt"))</PackageReleaseNotes> <PackageReleaseNotes>$([System.IO.File]::ReadAllText("$(MSBuildProjectDirectory)/ReleaseNotes.txt"))</PackageReleaseNotes>
<Version>2.0.0</Version> <Version>2.1.0</Version>
<PackageIcon>logo.png</PackageIcon> <PackageIcon>logo.png</PackageIcon>
<PackageReadmeFile>README.md</PackageReadmeFile> <PackageReadmeFile>README.md</PackageReadmeFile>
<Company>Toodle HomeLab</Company> <Company>Toodle HomeLab</Company>

View File

@ -1,4 +1,6 @@
using MediatR; // Copyright (c) 2020 Tudor Stanciu
using MediatR;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks; using System.Threading.Tasks;
using Tuitio.Application.CommandHandlers; using Tuitio.Application.CommandHandlers;
@ -27,12 +29,9 @@ namespace Tuitio.Controllers
[HttpPost("logout")] [HttpPost("logout")]
public async Task<IActionResult> Logout([FromQuery] string token) public async Task<IActionResult> Logout([FromQuery] string token)
{ {
var result = await _mediator.Send(token); var command = new AccountLogoutHandler.Command(token);
var result = await _mediator.Send(command);
if (result != null)
return Ok(result); return Ok(result);
else
return BadRequest();
} }
} }
} }

View File

@ -21,7 +21,7 @@ namespace Tuitio.Api.Controllers
[HttpPost("authorize")] [HttpPost("authorize")]
public async Task<IActionResult> AuthorizeToken([FromQuery] string token) public async Task<IActionResult> AuthorizeToken([FromQuery] string token)
{ {
var command = new AuthorizeTokenHandler.Command(token); var command = new AuthorizationHandler.Command(token);
var result = await _mediator.Send(command); var result = await _mediator.Send(command);
return Ok(result); return Ok(result);
} }

View File

@ -11,11 +11,8 @@ namespace Tuitio.Api.Controllers
[Route("system")] [Route("system")]
public class SystemController : ControllerBase public class SystemController : ControllerBase
{ {
private readonly IMediator _mediator;
public SystemController(IMediator mediator) public SystemController(IMediator mediator)
{ {
_mediator = mediator;
} }
[AllowAnonymous] [AllowAnonymous]
@ -24,12 +21,5 @@ namespace Tuitio.Api.Controllers
{ {
return Ok($"Ping success. System datetime: {DateTime.Now}"); return Ok($"Ping success. System datetime: {DateTime.Now}");
} }
/*
Methods:
/version
/burn-token
/burn-all-tokens
*/
} }
} }