refactor(backend): move all request/response types to a new Dto namespace

This commit is contained in:
sam 2024-12-08 20:17:30 +01:00
parent f8e6032449
commit 8bd4449804
Signed by: sam
GPG key ID: B4EF20DDE721CAA1
21 changed files with 310 additions and 316 deletions

View file

@ -2,14 +2,12 @@ using System.Net;
using System.Web;
using Foxnouns.Backend.Database;
using Foxnouns.Backend.Database.Models;
using Foxnouns.Backend.Dto;
using Foxnouns.Backend.Extensions;
using Foxnouns.Backend.Middleware;
using Foxnouns.Backend.Services;
using Foxnouns.Backend.Utils;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;
using NodaTime;
namespace Foxnouns.Backend.Controllers.Authentication;
@ -47,28 +45,6 @@ public class AuthController(
return Ok(new UrlsResponse(config.EmailAuth.Enabled, discord, null, null));
}
private record UrlsResponse(bool EmailEnabled, string? Discord, string? Google, string? Tumblr);
public record AuthResponse(
UserRendererService.UserResponse User,
string Token,
Instant ExpiresAt
);
public record SingleUrlResponse(string Url);
public record AddOauthAccountResponse(
Snowflake Id,
[property: JsonConverter(typeof(ScreamingSnakeCaseEnumConverter))] AuthType Type,
string RemoteId,
[property: JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
string? RemoteUsername
);
public record OauthRegisterRequest(string Ticket, string Username);
public record CallbackRequest(string Code, string State);
[HttpPost("force-log-out")]
[Authorize("identify")]
public async Task<IActionResult> ForceLogoutAsync()
@ -83,9 +59,7 @@ public class AuthController(
[HttpGet("methods/{id}")]
[Authorize("*")]
[ProducesResponseType<UserRendererService.AuthMethodResponse>(
statusCode: StatusCodes.Status200OK
)]
[ProducesResponseType<AuthMethodResponse>(statusCode: StatusCodes.Status200OK)]
public async Task<IActionResult> GetAuthMethodAsync(Snowflake id)
{
AuthMethod? authMethod = await db
@ -143,13 +117,3 @@ public class AuthController(
return NoContent();
}
}
public record CallbackResponse(
bool HasAccount,
[property: JsonProperty(NullValueHandling = NullValueHandling.Ignore)] string? Ticket,
[property: JsonProperty(NullValueHandling = NullValueHandling.Ignore)] string? RemoteUsername,
[property: JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
UserRendererService.UserResponse? User,
[property: JsonProperty(NullValueHandling = NullValueHandling.Ignore)] string? Token,
[property: JsonProperty(NullValueHandling = NullValueHandling.Ignore)] Instant? ExpiresAt
);

View file

@ -3,6 +3,7 @@ using System.Web;
using EntityFramework.Exceptions.Common;
using Foxnouns.Backend.Database;
using Foxnouns.Backend.Database.Models;
using Foxnouns.Backend.Dto;
using Foxnouns.Backend.Extensions;
using Foxnouns.Backend.Middleware;
using Foxnouns.Backend.Services;
@ -29,7 +30,7 @@ public class DiscordAuthController(
[HttpPost("callback")]
[ProducesResponseType<CallbackResponse>(StatusCodes.Status200OK)]
public async Task<IActionResult> CallbackAsync([FromBody] AuthController.CallbackRequest req)
public async Task<IActionResult> CallbackAsync([FromBody] CallbackRequest req)
{
CheckRequirements();
await keyCacheService.ValidateAuthStateAsync(req.State);
@ -58,10 +59,8 @@ public class DiscordAuthController(
}
[HttpPost("register")]
[ProducesResponseType<AuthController.AuthResponse>(StatusCodes.Status200OK)]
public async Task<IActionResult> RegisterAsync(
[FromBody] AuthController.OauthRegisterRequest req
)
[ProducesResponseType<AuthResponse>(StatusCodes.Status200OK)]
public async Task<IActionResult> RegisterAsync([FromBody] OauthRegisterRequest req)
{
RemoteAuthService.RemoteUser? remoteUser =
await keyCacheService.GetKeyAsync<RemoteAuthService.RemoteUser>(
@ -109,14 +108,12 @@ public class DiscordAuthController(
+ $"&prompt=none&state={state}"
+ $"&redirect_uri={HttpUtility.UrlEncode($"{config.BaseUrl}/auth/callback/discord")}";
return Ok(new AuthController.SingleUrlResponse(url));
return Ok(new SingleUrlResponse(url));
}
[HttpPost("add-account/callback")]
[Authorize("*")]
public async Task<IActionResult> AddAccountCallbackAsync(
[FromBody] AuthController.CallbackRequest req
)
public async Task<IActionResult> AddAccountCallbackAsync([FromBody] CallbackRequest req)
{
CheckRequirements();
@ -144,7 +141,7 @@ public class DiscordAuthController(
);
return Ok(
new AuthController.AddOauthAccountResponse(
new AddOauthAccountResponse(
authMethod.Id,
AuthType.Discord,
authMethod.RemoteId,

View file

@ -2,6 +2,7 @@ using System.Net;
using EntityFramework.Exceptions.Common;
using Foxnouns.Backend.Database;
using Foxnouns.Backend.Database.Models;
using Foxnouns.Backend.Dto;
using Foxnouns.Backend.Extensions;
using Foxnouns.Backend.Middleware;
using Foxnouns.Backend.Services;
@ -30,7 +31,7 @@ public class EmailAuthController(
[HttpPost("register/init")]
public async Task<IActionResult> RegisterInitAsync(
[FromBody] RegisterRequest req,
[FromBody] EmailRegisterRequest req,
CancellationToken ct = default
)
{
@ -73,7 +74,7 @@ public class EmailAuthController(
[HttpPost("register")]
public async Task<IActionResult> CompleteRegistrationAsync(
[FromBody] CompleteRegistrationRequest req
[FromBody] EmailCompleteRegistrationRequest req
)
{
CheckRequirements();
@ -102,7 +103,7 @@ public class EmailAuthController(
await keyCacheService.DeleteKeyAsync($"email:{req.Ticket}");
return Ok(
new AuthController.AuthResponse(
new AuthResponse(
await userRenderer.RenderUserAsync(user, user, renderMembers: false),
tokenStr,
token.ExpiresAt
@ -111,9 +112,9 @@ public class EmailAuthController(
}
[HttpPost("login")]
[ProducesResponseType<AuthController.AuthResponse>(StatusCodes.Status200OK)]
[ProducesResponseType<AuthResponse>(StatusCodes.Status200OK)]
public async Task<IActionResult> LoginAsync(
[FromBody] LoginRequest req,
[FromBody] EmailLoginRequest req,
CancellationToken ct = default
)
{
@ -141,7 +142,7 @@ public class EmailAuthController(
await db.SaveChangesAsync(ct);
return Ok(
new AuthController.AuthResponse(
new AuthResponse(
await userRenderer.RenderUserAsync(user, user, renderMembers: false, ct: ct),
tokenStr,
token.ExpiresAt
@ -151,7 +152,7 @@ public class EmailAuthController(
[HttpPost("change-password")]
[Authorize("*")]
public async Task<IActionResult> UpdatePasswordAsync([FromBody] ChangePasswordRequest req)
public async Task<IActionResult> UpdatePasswordAsync([FromBody] EmailChangePasswordRequest req)
{
if (!await authService.ValidatePasswordAsync(CurrentUser!, req.Current))
throw new ApiError.Forbidden("Invalid password");
@ -211,7 +212,7 @@ public class EmailAuthController(
[HttpPost("add-email/callback")]
[Authorize("*")]
public async Task<IActionResult> AddEmailCallbackAsync([FromBody] CallbackRequest req)
public async Task<IActionResult> AddEmailCallbackAsync([FromBody] EmailCallbackRequest req)
{
CheckRequirements();
@ -233,7 +234,7 @@ public class EmailAuthController(
);
return Ok(
new AuthController.AddOauthAccountResponse(
new AddOauthAccountResponse(
authMethod.Id,
AuthType.Email,
authMethod.RemoteId,
@ -258,14 +259,4 @@ public class EmailAuthController(
if (!config.EmailAuth.Enabled)
throw new ApiError.BadRequest("Email authentication is not enabled on this instance.");
}
public record LoginRequest(string Email, string Password);
public record RegisterRequest(string Email);
public record CompleteRegistrationRequest(string Ticket, string Username, string Password);
public record CallbackRequest(string State);
public record ChangePasswordRequest(string Current, string New);
}

View file

@ -2,6 +2,7 @@ using System.Net;
using EntityFramework.Exceptions.Common;
using Foxnouns.Backend.Database;
using Foxnouns.Backend.Database.Models;
using Foxnouns.Backend.Dto;
using Foxnouns.Backend.Middleware;
using Foxnouns.Backend.Services;
using Foxnouns.Backend.Services.Auth;
@ -25,7 +26,7 @@ public class FediverseAuthController(
private readonly ILogger _logger = logger.ForContext<FediverseAuthController>();
[HttpGet]
[ProducesResponseType<AuthController.SingleUrlResponse>(statusCode: StatusCodes.Status200OK)]
[ProducesResponseType<SingleUrlResponse>(statusCode: StatusCodes.Status200OK)]
public async Task<IActionResult> GetFediverseUrlAsync(
[FromQuery] string instance,
[FromQuery] bool forceRefresh = false
@ -35,12 +36,12 @@ public class FediverseAuthController(
throw new ApiError.BadRequest("Not a valid domain.", "instance", instance);
string url = await fediverseAuthService.GenerateAuthUrlAsync(instance, forceRefresh);
return Ok(new AuthController.SingleUrlResponse(url));
return Ok(new SingleUrlResponse(url));
}
[HttpPost("callback")]
[ProducesResponseType<CallbackResponse>(statusCode: StatusCodes.Status200OK)]
public async Task<IActionResult> FediverseCallbackAsync([FromBody] CallbackRequest req)
public async Task<IActionResult> FediverseCallbackAsync([FromBody] FediverseCallbackRequest req)
{
FediverseApplication app = await fediverseAuthService.GetApplicationAsync(req.Instance);
FediverseAuthService.FediverseUser remoteUser =
@ -74,10 +75,8 @@ public class FediverseAuthController(
}
[HttpPost("register")]
[ProducesResponseType<AuthController.AuthResponse>(statusCode: StatusCodes.Status200OK)]
public async Task<IActionResult> RegisterAsync(
[FromBody] AuthController.OauthRegisterRequest req
)
[ProducesResponseType<AuthResponse>(statusCode: StatusCodes.Status200OK)]
public async Task<IActionResult> RegisterAsync([FromBody] OauthRegisterRequest req)
{
FediverseTicketData? ticketData = await keyCacheService.GetKeyAsync<FediverseTicketData>(
$"fediverse:{req.Ticket}",
@ -138,12 +137,14 @@ public class FediverseAuthController(
);
string url = await fediverseAuthService.GenerateAuthUrlAsync(instance, forceRefresh, state);
return Ok(new AuthController.SingleUrlResponse(url));
return Ok(new SingleUrlResponse(url));
}
[HttpPost("add-account/callback")]
[Authorize("*")]
public async Task<IActionResult> AddAccountCallbackAsync([FromBody] CallbackRequest req)
public async Task<IActionResult> AddAccountCallbackAsync(
[FromBody] FediverseCallbackRequest req
)
{
await remoteAuthService.ValidateAddAccountStateAsync(
req.State,
@ -171,7 +172,7 @@ public class FediverseAuthController(
);
return Ok(
new AuthController.AddOauthAccountResponse(
new AddOauthAccountResponse(
authMethod.Id,
AuthType.Fediverse,
authMethod.RemoteId,
@ -189,8 +190,6 @@ public class FediverseAuthController(
}
}
public record CallbackRequest(string Instance, string Code, string State);
private record FediverseTicketData(
Snowflake ApplicationId,
FediverseAuthService.FediverseUser User