Adds a [Altcha]-decorated ProtectedActionCommand with IHasAltchaSolution and a StubAltchaVerifier that treats the literal "valid-solution" as passing PoW. Exercises both the HTTP MinimalApi and gRPC pipelines without requiring an external altcha service. Validated 4 scenarios on each transport (8 total, all pass): HTTP /api/command/protectedAction POST 6001 gRPC :6000 ------------------------------------------------------------------- no AltchaSolution 401 Unauthenticated AltchaSolution = "wrong" 401 Unauthenticated AltchaSolution = "valid-solution" 200 result OK + result addUser (no [Altcha]) 200 result OK + result The last row confirms backward compatibility: a request type that isn't decorated with [Altcha] bypasses the check entirely — the AltchaAuthorizationCheck self-applies and no-ops, and any consumer that doesn't call AddSvrntyAltcha() sees zero behavior change. Generated CommandServiceImpl.g.cs verified to include the ICommandAuthorizationCheck loop after validation, before handler invocation, with the materialized command instance in ctx.Command. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
38 lines
1.4 KiB
C#
38 lines
1.4 KiB
C#
using Svrnty.CQRS.Abstractions;
|
|
using Svrnty.CQRS.Altcha.Abstractions;
|
|
|
|
namespace Svrnty.Sample;
|
|
|
|
// Exercises the ICommandAuthorizationCheck seam at runtime.
|
|
// The command is decorated with [Altcha] and carries the solution
|
|
// through IHasAltchaSolution. With Svrnty.CQRS.Altcha + a registered
|
|
// IAltchaVerifier, the framework's check pipeline reads the field,
|
|
// calls the verifier, and short-circuits on failure.
|
|
[Altcha]
|
|
public sealed class ProtectedActionCommand : IHasAltchaSolution
|
|
{
|
|
public string Action { get; set; } = string.Empty;
|
|
public string? AltchaSolution { get; set; }
|
|
}
|
|
|
|
public sealed class ProtectedActionCommandHandler : ICommandHandler<ProtectedActionCommand, string>
|
|
{
|
|
public Task<string> HandleAsync(ProtectedActionCommand command, CancellationToken cancellationToken = default)
|
|
{
|
|
return Task.FromResult($"executed:{command.Action}");
|
|
}
|
|
}
|
|
|
|
// Stub verifier that doesn't talk to an external altcha service —
|
|
// enough to exercise the check pipeline in isolation. Treats the
|
|
// literal string "valid-solution" as a passing PoW solution.
|
|
public sealed class StubAltchaVerifier : IAltchaVerifier
|
|
{
|
|
public Task<AltchaVerifyResult> VerifyAsync(string payload, CancellationToken cancellationToken = default)
|
|
{
|
|
if (payload == "valid-solution")
|
|
return Task.FromResult(AltchaVerifyResult.Success);
|
|
return Task.FromResult(AltchaVerifyResult.Fail("stub-rejected"));
|
|
}
|
|
}
|