feat: add presence-gated session leases (#7)
quality-gate / quality (push) Successful in 55s
quality-gate / quality (push) Successful in 55s
Closes #7
This commit is contained in:
@@ -2,6 +2,7 @@ using System.Net;
|
||||
using FinalFactory.Rendezvous.Contracts;
|
||||
using FinalFactory.Rendezvous.Server.Http;
|
||||
using FinalFactory.Rendezvous.Server.Provisioning;
|
||||
using FinalFactory.Rendezvous.Server.Sessions;
|
||||
using FinalFactory.Rendezvous.Server.State;
|
||||
using FinalFactory.Rendezvous.Server.Transport;
|
||||
using Microsoft.OpenApi;
|
||||
@@ -13,6 +14,7 @@ bool isOpenApiGeneration = string.Equals(
|
||||
StringComparison.Ordinal);
|
||||
|
||||
builder.Services.AddOpenApi("v1", static options =>
|
||||
{
|
||||
options.AddSchemaTransformer(static (schema, context, cancellationToken) =>
|
||||
{
|
||||
Type type = context.JsonTypeInfo.Type;
|
||||
@@ -32,16 +34,65 @@ builder.Services.AddOpenApi("v1", static options =>
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}));
|
||||
});
|
||||
options.AddDocumentTransformer(static (document, context, cancellationToken) =>
|
||||
{
|
||||
const string schemeName = "PublisherBearer";
|
||||
document.Components ??= new OpenApiComponents();
|
||||
document.Components.SecuritySchemes ??=
|
||||
new Dictionary<string, IOpenApiSecurityScheme>(StringComparer.Ordinal);
|
||||
document.Components.SecuritySchemes[schemeName] = new OpenApiSecurityScheme
|
||||
{
|
||||
Type = SecuritySchemeType.Http,
|
||||
Scheme = "bearer",
|
||||
BearerFormat = "rv1 publisher credential",
|
||||
Description = "Tenant-scoped publisher credential issued during game provisioning.",
|
||||
};
|
||||
|
||||
HashSet<string> securedOperations = new(StringComparer.Ordinal)
|
||||
{
|
||||
"RegisterSession",
|
||||
"RenewSessionLease",
|
||||
"UpdateSession",
|
||||
"DeleteSession",
|
||||
};
|
||||
OpenApiSecuritySchemeReference reference = new(schemeName, document, null);
|
||||
foreach (OpenApiPathItem path in document.Paths.Values)
|
||||
{
|
||||
if (path.Operations is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (OpenApiOperation operation in path.Operations.Values.Where(
|
||||
operation => securedOperations.Contains(operation.OperationId ?? string.Empty)))
|
||||
{
|
||||
operation.Security ??= [];
|
||||
operation.Security.Add(new OpenApiSecurityRequirement
|
||||
{
|
||||
[reference] = [],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
});
|
||||
builder.Services.ConfigureHttpJsonOptions(static options =>
|
||||
ContractJson.Configure(options.SerializerOptions));
|
||||
builder.Services.Configure<RouteHandlerOptions>(static options =>
|
||||
options.ThrowOnBadRequest = true);
|
||||
builder.Services.AddProblemDetails();
|
||||
builder.Services.AddExceptionHandler<RendezvousExceptionHandler>();
|
||||
|
||||
SystemRendezvousClock rendezvousClock = new();
|
||||
EphemeralStoreOptions stateOptions = new();
|
||||
InMemoryEphemeralRendezvousStore stateStore = new(
|
||||
new EphemeralStoreOptions(),
|
||||
stateOptions,
|
||||
rendezvousClock,
|
||||
rendezvousClock);
|
||||
builder.Services.AddSingleton<IEphemeralRendezvousStore>(stateStore);
|
||||
builder.Services.AddSingleton<IWallClock>(rendezvousClock);
|
||||
|
||||
if (isOpenApiGeneration)
|
||||
{
|
||||
@@ -63,6 +114,11 @@ else
|
||||
builder.Services.AddSingleton(provisioning.Policies);
|
||||
builder.Services.AddSingleton(provisioning.Credentials);
|
||||
builder.Services.AddSingleton(provisioning.PublisherAuthorization);
|
||||
EphemeralCapabilityIssuer sessionCapabilities = new();
|
||||
builder.Services.AddSingleton(sessionCapabilities);
|
||||
builder.Services.AddSingleton<ISessionCapabilityService>(sessionCapabilities);
|
||||
builder.Services.AddSingleton(SessionLeaseTiming.From(stateOptions));
|
||||
builder.Services.AddSingleton<SessionLeaseService>();
|
||||
builder.Services.AddSingleton(new ProvisioningReadiness(true));
|
||||
}
|
||||
|
||||
@@ -84,6 +140,7 @@ if (!isOpenApiGeneration)
|
||||
WebApplication app = builder.Build();
|
||||
app.Lifetime.ApplicationStopping.Register(() => stateStore.BeginDrain());
|
||||
|
||||
app.UseExceptionHandler();
|
||||
app.MapOpenApi();
|
||||
app.MapRendezvousContractEndpoints();
|
||||
app.MapGet(
|
||||
|
||||
Reference in New Issue
Block a user