VanguardReMaster/server/src/Vanguard.Server/Auth/AuthEndpoints.cs

148 lines
4.1 KiB
C#

using System.Security.Claims;
using Vanguard.Server.Api;
using Vanguard.Server.Auth;
using Vanguard.Server.Meta;
namespace Vanguard.Server.Auth;
public sealed record RegisterRequest(string? UserName, string? Password);
public sealed record LoginRequest(string? UserName, string? Password);
public sealed record RefreshRequest(string? RefreshToken);
public sealed record AuthResponse(
Guid UserId,
string UserName,
string AccessToken,
string RefreshToken,
DateTimeOffset AccessExpiresAt,
DateTimeOffset RefreshExpiresAt,
bool OnboardingCompleted);
public sealed record MeResponse(
Guid UserId,
string UserName,
DateTimeOffset CreatedAt,
bool OnboardingCompleted,
string? SelectedTrialDeckId,
int Gold,
int Dust,
int Tokens,
int Xp,
int RankedMmr,
int CasualMmr,
int Matches,
int Wins);
public static class AuthEndpoints
{
public static void MapAuthEndpoints(this WebApplication app)
{
var group = app.MapGroup("/api/auth");
group.MapPost("/register", Register).RequireRateLimiting("auth");
group.MapPost("/login", Login).RequireRateLimiting("auth");
group.MapPost("/refresh", Refresh).RequireRateLimiting("auth");
group.MapPost("/logout", Logout);
group.MapGet("/me", Me).RequireAuthorization();
}
private static async Task<IResult> Register(
RegisterRequest request,
AuthService auth)
{
try
{
var result = await auth.RegisterAsync(request.UserName, request.Password);
return Results.Ok(ToResponse(result));
}
catch (AuthException exception)
{
return Results.Json(
new ApiError(exception.Code, exception.Message),
statusCode: exception.StatusCode);
}
}
private static async Task<IResult> Login(
LoginRequest request,
AuthService auth)
{
try
{
var result = await auth.LoginAsync(request.UserName, request.Password);
return Results.Ok(ToResponse(result));
}
catch (AuthException exception)
{
return Results.Json(
new ApiError(exception.Code, exception.Message),
statusCode: exception.StatusCode);
}
}
private static async Task<IResult> Refresh(
RefreshRequest request,
AuthService auth)
{
try
{
var result = await auth.RefreshAsync(request.RefreshToken);
return Results.Ok(ToResponse(result));
}
catch (AuthException exception)
{
return Results.Json(
new ApiError(exception.Code, exception.Message),
statusCode: exception.StatusCode);
}
}
private static async Task<IResult> Logout(
RefreshRequest request,
AuthService auth)
{
await auth.LogoutAsync(request.RefreshToken);
return Results.NoContent();
}
private static async Task<IResult> Me(
ClaimsPrincipal principal,
AuthService auth,
EconomyService economy)
{
var userId = principal.GetUserId();
if (userId is null)
return Results.Unauthorized();
var user = await auth.GetUserAsync(userId.Value);
if (user is null)
return Results.Unauthorized();
var balances = await economy.GetBalancesAsync(user.Id);
return Results.Ok(new MeResponse(
user.Id,
user.UserName,
user.CreatedAt,
user.OnboardingCompleted,
user.SelectedTrialDeckId,
balances.Gold,
balances.Dust,
balances.Tokens,
user.Xp,
user.RankedMmr,
user.CasualMmr,
user.Matches,
user.Wins));
}
private static AuthResponse ToResponse(AuthResult result) => new(
result.User.Id,
result.User.UserName,
result.Tokens.AccessToken,
result.Tokens.RefreshToken,
result.Tokens.AccessExpiresAt,
result.Tokens.RefreshExpiresAt,
result.User.OnboardingCompleted);
}