Files
2026-07-23 18:21:43 -07:00

161 lines
5.7 KiB
C#

using DeluxeBackend.Models;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Numerics;
using System.Security.Claims;
using static DeluxeBackend.Enums;
namespace DeluxeBackend.Services
{
public class LoginWithInfoResult
{
public required Account Account { get; set; }
public PlatformType Platform { get; set; }
public required string PlatformId { get; set; }
public DeviceClassType DeviceClass { get; set; }
public required string Locale { get; set; }
public required string AppVersion { get; set; }
}
public interface IJwtService
{
Task<string> GenAccessToken(Account account, List<string> roles, Dictionary<string, object>? customeClaims = null);
Task<string> GenRefreshToken(Account acc);
Task<Account?> GetLogin(ClaimsPrincipal? User);
Task<LoginWithInfoResult?> GetLoginWithInfo(ClaimsPrincipal? User);
}
public class JwtService : IJwtService
{
private readonly ILiteDbService db;
private readonly IConfiguration configuration;
private readonly DiscordBotService discord;
public JwtService(ILiteDbService _db, IConfiguration _configuration, DiscordBotService _discord)
{
db = _db;
configuration = _configuration;
discord = _discord;
}
public async Task<string> GenAccessToken(Account account, List<string> roles, Dictionary<string, object>? customeClaims = null)
{
var issuer = configuration["JwtConfig:Issuer"];
var key = new SymmetricSecurityKey(Convert.FromBase64String(configuration["JwtConfig:Key"]));
var exp = DateTime.UtcNow.AddHours(1).AddMinutes(10);
roles.AddRange(account.Roles);
if (account.DiscordId.HasValue)
{
roles.AddRange(await discord.UserRoles(account.DiscordId.Value));
}
if (account.IsJunior == null || account.IsJunior == true)
{
roles.Add("junior");
}
roles = roles.Distinct().ToList();
var claimsDictionary = new Dictionary<string, object>
{
["role"] = roles
};
if (customeClaims != null)
{
foreach (var claim in customeClaims)
{
claimsDictionary[claim.Key] = claim.Value;
}
}
var tokenDect = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(
[
new Claim("sub", account.Id.ToString())
]),
IssuedAt = DateTime.UtcNow,
Claims = claimsDictionary,
Expires = exp,
Issuer = issuer,
SigningCredentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256Signature),
};
var tokenHandler = new JwtSecurityTokenHandler();
var token = tokenHandler.WriteToken(tokenHandler.CreateToken(tokenDect));
return token;
}
public Task<string> GenRefreshToken(Account acc)
{
RefreshToken refreshToken = new()
{
Token = Convert.ToBase64String(Guid.NewGuid().ToByteArray()),
Expires = DateTime.UtcNow.AddDays(2),
Account = acc
};
db.RefreshTokens.Insert(refreshToken);
return Task.FromResult(refreshToken.Token);
}
public Task<Account?> GetLogin(ClaimsPrincipal? User = null)
{
Console.WriteLine(User);
if (User == null)
return Task.FromResult<Account?>(null);
string? rawPlayerId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value
?? User.FindFirst("sub")?.Value;
if (string.IsNullOrEmpty(rawPlayerId))
return Task.FromResult<Account?>(null);
if (!long.TryParse(rawPlayerId, out long playerId))
return Task.FromResult<Account?>(null);
Account? player = db.Accounts.FindById(playerId);
return Task.FromResult<Account?>(player);
}
public Task<LoginWithInfoResult?> GetLoginWithInfo(ClaimsPrincipal? User = null)
{
if (User == null)
return Task.FromResult<LoginWithInfoResult?>(null);
string? rawPlayerId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value
?? User.FindFirst("sub")?.Value;
if (string.IsNullOrEmpty(rawPlayerId) || !long.TryParse(rawPlayerId, out long playerId))
return Task.FromResult<LoginWithInfoResult?>(null);
Account? player = db.Accounts.FindById(playerId);
if (player == null)
return Task.FromResult<LoginWithInfoResult?>(null);
var result = new LoginWithInfoResult
{
Account = player,
PlatformId = User.FindFirst("db.platform.id")?.Value,
Locale = User.FindFirst("db.locale")?.Value,
AppVersion= User.FindFirst("db.appver")?.Value,
};
string? rawPlatform = User.FindFirst("db.platform")?.Value;
if (Enum.TryParse<PlatformType>(rawPlatform, out var platform))
{
result.Platform = platform;
}
string? rawDeviceClass = User.FindFirst("db.deviceclass")?.Value;
if (Enum.TryParse<DeviceClassType>(rawDeviceClass, out var deviceClass))
{
result.DeviceClass = deviceClass;
}
return Task.FromResult<LoginWithInfoResult?>(result);
}
}
}