using HashidsNet; using JWT.Algorithms; using JWT.Builder; using JWT.Serializers; using LanguageExt.Common; using Security.Scheme; using W542.GandalfReborn.Commands; using W542.GandalfReborn.Data.Database.Repositories; using W542.GandalfReborn.Data.Dto; using W542.GandalfReborn.Data.Entities.Security; using W542.GandalfReborn.Extensions; using W542.GandalfReborn.Handlers.Commands; namespace W542.GandalfReborn.Handlers.Security; public class CreateTokensCommandHandler(TimeProvider timeProvider, IConfiguration configuration, IHashids hashids, ITokenMetadataRepository tokenMetadataRepository) : IGrCommandHandler> { public async Task> Handle(CreateTokensCommand command, CancellationToken cancellationToken) { var iat = timeProvider.GetUtcNow(); var accessExp = iat.AddMinutes(5); var refreshExp = iat.AddDays(7); var builder = JwtBuilder.Create() .WithAlgorithm(new HMACSHA512Algorithm()) .WithSecret(configuration.GetValue("JwtSecret")) .WithJsonSerializer(new JsonNetSerializer()); var accessTokenMetadata = new TokenMetadataEntity { Expiration = accessExp, IsRevoked = false, TokenType = TokenType.User, UsedBy = command.SubjectId }; var refreshTokenMetadata = new TokenMetadataEntity { Expiration = refreshExp, IsRevoked = false, TokenType = TokenType.User, UsedBy = command.SubjectId }; var entities = await tokenMetadataRepository.Upsert([accessTokenMetadata, refreshTokenMetadata]); if (entities.IsFaulted) return entities.AsErrorResult>(); var baseUrl = configuration.GetValue("BaseUrl") ?? "https://localhost:7269"; var accessToken = builder.Encode(new GandalfRebornJwtBody { Id = hashids.EncodeLong(accessTokenMetadata.Id!.Value), Sub = hashids.EncodeLong(command.SubjectId), Iat = iat, Exp = accessExp, Iss = baseUrl, Aud = baseUrl }); var refreshToken = builder.Encode(new GandalfRebornJwtBody { Id = hashids.EncodeLong(refreshTokenMetadata.Id!.Value), Sub = hashids.EncodeLong(command.SubjectId), Iat = iat, Exp = refreshExp, Iss = baseUrl, Aud = baseUrl }); return new Result(new TokenDto { AccessToken = accessToken, RefreshToken = refreshToken }); } }