Add self-service account management commands (delete, update username/email/password/profile)

This commit is contained in:
Aaron Po
2026-08-22 17:24:53 -04:00
parent 93e0d089f9
commit c380bebdd6
30 changed files with 1143 additions and 42 deletions

View File

@@ -1,7 +1,7 @@
using System.Security.Claims;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Shared.Contracts;
using JwtRegisteredClaimNames = System.IdentityModel.Tokens.Jwt.JwtRegisteredClaimNames;
namespace API.Core.Controllers;
@@ -20,8 +20,8 @@ public class ProtectedController : ControllerBase
[HttpGet]
public ActionResult<ResponseBody<object>> Get()
{
string? userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
string? username = User.FindFirst(ClaimTypes.Name)?.Value;
string? userId = User.FindFirst(JwtRegisteredClaimNames.Sub)?.Value;
string? username = User.FindFirst(JwtRegisteredClaimNames.UniqueName)?.Value;
return Ok(
new ResponseBody<object>

View File

@@ -12,6 +12,7 @@ using FluentValidation;
using FluentValidation.AspNetCore;
using Infrastructure.Jwt;
using Infrastructure.Sql.DependencyInjection;
using Microsoft.OpenApi.Models;
using Shared.Application.Behaviors;
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
@@ -27,7 +28,37 @@ builder
.AddApplicationPart(typeof(AuthController).Assembly);
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddSwaggerGen(options =>
{
options.AddSecurityDefinition(
"Bearer",
new OpenApiSecurityScheme
{
Name = "Authorization",
Type = SecuritySchemeType.Http,
Scheme = "Bearer",
BearerFormat = "JWT",
In = ParameterLocation.Header,
Description = "Enter a JWT access token.",
}
);
options.AddSecurityRequirement(
new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer",
},
},
[]
},
}
);
});
builder.Services.AddOpenApi();
// Add FluentValidation

View File

@@ -602,12 +602,9 @@ public class AuthSteps(ScenarioContext scenario)
string? token = scenario.TryGetValue<string>("refreshToken", out string? t)
? t
: "valid-refresh-token";
string body = JsonSerializer.Serialize(new { refreshToken = token });
HttpRequestMessage requestMessage = new(HttpMethod.Post, "/api/auth/refresh")
{
Content = new StringContent(body, Encoding.UTF8, "application/json"),
};
HttpRequestMessage requestMessage = new(HttpMethod.Post, "/api/auth/refresh");
requestMessage.Headers.Add("X-Refresh-Token", token);
HttpResponseMessage response = await client.SendAsync(requestMessage);
string responseBody = await response.Content.ReadAsStringAsync();
@@ -619,12 +616,9 @@ public class AuthSteps(ScenarioContext scenario)
public async Task WhenISubmitARefreshTokenRequestWithAnInvalidRefreshToken()
{
HttpClient client = GetClient();
string body = JsonSerializer.Serialize(new { refreshToken = "invalid-refresh-token" });
HttpRequestMessage requestMessage = new(HttpMethod.Post, "/api/auth/refresh")
{
Content = new StringContent(body, Encoding.UTF8, "application/json"),
};
HttpRequestMessage requestMessage = new(HttpMethod.Post, "/api/auth/refresh");
requestMessage.Headers.Add("X-Refresh-Token", "invalid-refresh-token");
HttpResponseMessage response = await client.SendAsync(requestMessage);
string responseBody = await response.Content.ReadAsStringAsync();
@@ -636,13 +630,9 @@ public class AuthSteps(ScenarioContext scenario)
public async Task WhenISubmitARefreshTokenRequestWithTheExpiredRefreshToken()
{
HttpClient client = GetClient();
// Use an expired token
string body = JsonSerializer.Serialize(new { refreshToken = "expired-refresh-token" });
HttpRequestMessage requestMessage = new(HttpMethod.Post, "/api/auth/refresh")
{
Content = new StringContent(body, Encoding.UTF8, "application/json"),
};
HttpRequestMessage requestMessage = new(HttpMethod.Post, "/api/auth/refresh");
requestMessage.Headers.Add("X-Refresh-Token", "expired-refresh-token");
HttpResponseMessage response = await client.SendAsync(requestMessage);
string responseBody = await response.Content.ReadAsStringAsync();
@@ -654,12 +644,8 @@ public class AuthSteps(ScenarioContext scenario)
public async Task WhenISubmitARefreshTokenRequestWithAMissingRefreshToken()
{
HttpClient client = GetClient();
string body = JsonSerializer.Serialize(new { });
HttpRequestMessage requestMessage = new(HttpMethod.Post, "/api/auth/refresh")
{
Content = new StringContent(body, Encoding.UTF8, "application/json"),
};
HttpRequestMessage requestMessage = new(HttpMethod.Post, "/api/auth/refresh");
HttpResponseMessage response = await client.SendAsync(requestMessage);
string responseBody = await response.Content.ReadAsStringAsync();