cambios en apidenuncias
This commit is contained in:
@@ -15,9 +15,7 @@ var builder = WebApplication.CreateBuilder(args);
|
||||
CultureInfo.DefaultThreadCurrentCulture = CultureInfo.GetCultureInfo("es-ES");
|
||||
CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.GetCultureInfo("es-ES");
|
||||
|
||||
builder.Services.Configure<GestionaOptions>(builder.Configuration.GetSection("Gestiona"));
|
||||
builder.Services.Configure<GlobalLeaksOptions>(builder.Configuration.GetSection(GlobalLeaksOptions.SectionName));
|
||||
builder.Services.Configure<ComplaintStorageOptions>(builder.Configuration.GetSection(ComplaintStorageOptions.SectionName));
|
||||
builder.Services.Configure<ApiDenunciasOptions>(builder.Configuration.GetSection(ApiDenunciasOptions.SectionName));
|
||||
|
||||
builder.Services.AddRazorComponents()
|
||||
.AddInteractiveServerComponents();
|
||||
@@ -40,23 +38,18 @@ builder.Services.AddAuthorization();
|
||||
builder.Services.AddDataProtection();
|
||||
builder.Services.AddServerSideBlazor().AddCircuitOptions(option => { option.DetailedErrors = true; });
|
||||
builder.Services.AddHttpContextAccessor();
|
||||
builder.Services.AddBlazorBootstrap();
|
||||
builder.Services.AddAntiforgery();
|
||||
builder.Services.AddScoped<UserState>();
|
||||
builder.Services.AddSingleton<AppSessionLifetime>();
|
||||
builder.Services.AddSingleton<LoginRateLimiter>();
|
||||
builder.Services.AddSingleton<GlobalLeaksSessionStore>();
|
||||
builder.Services.AddScoped<GlobalLeaksClient>();
|
||||
builder.Services.AddScoped<IDenunciaStore, MySqlDenunciaStore>();
|
||||
builder.Services.AddScoped<IInboxTrackingService, InboxTrackingService>();
|
||||
builder.Services.AddScoped<DenunciaInboxService>();
|
||||
builder.Services.AddScoped<GestionaDocumentWorkflowService>();
|
||||
builder.Services.AddScoped<ApiDenunciasClient>();
|
||||
builder.Services.AddScoped<IDenunciaStore, ApiDenunciaStore>();
|
||||
builder.Services.AddScoped<IInboxTrackingService, ApiInboxTrackingService>();
|
||||
|
||||
builder.Services.AddHttpClient<IGestionaService, GestionaService>((sp, client) =>
|
||||
builder.Services.AddHttpClient(ApiDenunciasClient.HttpClientName, (sp, client) =>
|
||||
{
|
||||
var opts = sp.GetRequiredService<IOptions<GestionaOptions>>().Value;
|
||||
client.BaseAddress = new Uri(opts.ApiBase);
|
||||
client.DefaultRequestHeaders.Add("X-Gestiona-Access-Token", opts.AccessToken);
|
||||
var opts = sp.GetRequiredService<IOptions<ApiDenunciasOptions>>().Value;
|
||||
client.BaseAddress = new Uri(opts.BaseUrl.TrimEnd('/') + "/");
|
||||
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
||||
});
|
||||
|
||||
@@ -104,22 +97,20 @@ app.Use(async (context, next) =>
|
||||
var username = context.User.Identity?.Name?.Trim();
|
||||
var appSessionLifetime = context.RequestServices.GetRequiredService<AppSessionLifetime>();
|
||||
var cookieStartupStamp = context.User.FindFirst("app_startup_stamp")?.Value;
|
||||
var hasStoredCredentials = false;
|
||||
var hasApiToken = !string.IsNullOrWhiteSpace(context.User.FindFirst(ApiDenunciasClient.AccessTokenClaim)?.Value);
|
||||
var tokenIsStillValid = true;
|
||||
var cookieBelongsToCurrentStartup =
|
||||
!string.IsNullOrWhiteSpace(cookieStartupStamp) &&
|
||||
string.Equals(cookieStartupStamp, appSessionLifetime.StartupStamp, StringComparison.Ordinal);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(username))
|
||||
var tokenExpiresAt = context.User.FindFirst(ApiDenunciasClient.TokenExpiresAtClaim)?.Value;
|
||||
if (!string.IsNullOrWhiteSpace(tokenExpiresAt) &&
|
||||
DateTimeOffset.TryParse(tokenExpiresAt, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out var expiresAt))
|
||||
{
|
||||
var sessionStore = context.RequestServices.GetRequiredService<GlobalLeaksSessionStore>();
|
||||
var storedSession = await sessionStore.GetAsync(username, context.RequestAborted);
|
||||
hasStoredCredentials =
|
||||
storedSession is not null &&
|
||||
!string.IsNullOrWhiteSpace(storedSession.Username) &&
|
||||
!string.IsNullOrWhiteSpace(storedSession.Password);
|
||||
tokenIsStillValid = expiresAt > DateTimeOffset.UtcNow;
|
||||
}
|
||||
|
||||
if (!hasStoredCredentials || !cookieBelongsToCurrentStartup)
|
||||
if (string.IsNullOrWhiteSpace(username) || !hasApiToken || !tokenIsStillValid || !cookieBelongsToCurrentStartup)
|
||||
{
|
||||
await context.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
|
||||
|
||||
@@ -148,8 +139,7 @@ var api = app.MapGroup("/api");
|
||||
api.MapPost("/auth/login", async (
|
||||
LoginRequest request,
|
||||
HttpContext httpContext,
|
||||
GlobalLeaksClient globalLeaksClient,
|
||||
GlobalLeaksSessionStore sessionStore,
|
||||
ApiDenunciasClient apiClient,
|
||||
LoginRateLimiter rateLimiter,
|
||||
CancellationToken cancellationToken) =>
|
||||
{
|
||||
@@ -180,34 +170,25 @@ api.MapPost("/auth/login", async (
|
||||
|
||||
try
|
||||
{
|
||||
var session = await globalLeaksClient.LoginAsync(
|
||||
request.Username.Trim(),
|
||||
request.Password,
|
||||
request.Authcode.Trim(),
|
||||
cancellationToken);
|
||||
|
||||
var resolvedUsername = string.IsNullOrWhiteSpace(session.Username)
|
||||
? request.Username.Trim()
|
||||
: session.Username.Trim();
|
||||
|
||||
session = new GlSession(session.Id, resolvedUsername, session.Role);
|
||||
|
||||
await sessionStore.SaveAsync(
|
||||
session.Username,
|
||||
request.Password,
|
||||
session.Id,
|
||||
session.Role,
|
||||
var login = await apiClient.LoginAsync(
|
||||
request with
|
||||
{
|
||||
Username = request.Username.Trim(),
|
||||
Authcode = request.Authcode.Trim()
|
||||
},
|
||||
cancellationToken);
|
||||
|
||||
var claims = new List<Claim>
|
||||
{
|
||||
new(ClaimTypes.Name, session.Username),
|
||||
new(ClaimTypes.Name, login.Username),
|
||||
new("app_startup_stamp", appSessionLifetime.StartupStamp),
|
||||
new(ApiDenunciasClient.AccessTokenClaim, login.AccessToken),
|
||||
new(ApiDenunciasClient.TokenExpiresAtClaim, login.ExpiresAtUtc.ToString("O", CultureInfo.InvariantCulture)),
|
||||
};
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(session.Role))
|
||||
if (!string.IsNullOrWhiteSpace(login.Role))
|
||||
{
|
||||
claims.Add(new Claim("gl_role", session.Role));
|
||||
claims.Add(new Claim("gl_role", login.Role));
|
||||
}
|
||||
|
||||
var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
|
||||
@@ -223,29 +204,35 @@ api.MapPost("/auth/login", async (
|
||||
principal,
|
||||
authProperties);
|
||||
|
||||
return Results.Ok(new LoginResponse(session.Username));
|
||||
return Results.Ok(new LoginResponse(login.Username));
|
||||
}
|
||||
catch (GlobalLeaksValidationException ex)
|
||||
catch (UnauthorizedAccessException ex)
|
||||
{
|
||||
return Results.Json(new ApiError(ex.Message), statusCode: ex.StatusCode);
|
||||
return Results.Json(new ApiError(ex.Message), statusCode: StatusCodes.Status401Unauthorized);
|
||||
}
|
||||
catch
|
||||
catch (InvalidOperationException ex)
|
||||
{
|
||||
return Results.Json(
|
||||
new ApiError("No se ha podido conectar con GlobalLeaks."),
|
||||
statusCode: StatusCodes.Status502BadGateway);
|
||||
new ApiError(ex.Message),
|
||||
statusCode: StatusCodes.Status400BadRequest);
|
||||
}
|
||||
}).DisableAntiforgery();
|
||||
|
||||
api.MapPost("/auth/logout", async (
|
||||
HttpContext httpContext,
|
||||
GlobalLeaksSessionStore sessionStore,
|
||||
ApiDenunciasClient apiClient,
|
||||
CancellationToken cancellationToken) =>
|
||||
{
|
||||
var username = httpContext.User.Identity?.Name;
|
||||
if (!string.IsNullOrWhiteSpace(username))
|
||||
if (httpContext.User.Identity?.IsAuthenticated == true)
|
||||
{
|
||||
await sessionStore.DeleteAsync(username, cancellationToken);
|
||||
try
|
||||
{
|
||||
await apiClient.LogoutAsync(cancellationToken);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Aunque la API no responda, el usuario debe poder cerrar la sesion local.
|
||||
}
|
||||
}
|
||||
|
||||
await httpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
|
||||
|
||||
Reference in New Issue
Block a user