feat(auth): cut MxGateway API keys over to ZB.MOM.WW.Auth.ApiKeys 0.1.2; keep constraint enforcement+gRPC+CLI on top (Task 1.3)
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
using System.Globalization;
|
||||
using Microsoft.Extensions.Options;
|
||||
using ZB.MOM.WW.Auth.Abstractions.ApiKeys;
|
||||
using ZB.MOM.WW.MxGateway.Contracts.Proto;
|
||||
using ZB.MOM.WW.MxGateway.Server.Configuration;
|
||||
using ZB.MOM.WW.MxGateway.Server.Dashboard;
|
||||
@@ -273,16 +274,15 @@ public sealed class DashboardSnapshotServiceTests
|
||||
{
|
||||
using GatewayMetrics metrics = new();
|
||||
CountingApiKeyAdminStore apiKeyAdminStore = new(
|
||||
new ApiKeyRecord(
|
||||
new ApiKeyListItem(
|
||||
KeyId: "operator01",
|
||||
KeyPrefix: "mxgw_operator01",
|
||||
SecretHash: [1, 2, 3],
|
||||
KeyPrefix: "mxgw",
|
||||
DisplayName: "Operator",
|
||||
Scopes: new HashSet<string>([GatewayScopes.MetadataRead], StringComparer.Ordinal),
|
||||
Constraints: ApiKeyConstraints.Empty with
|
||||
ConstraintsJson: ApiKeyConstraintSerializer.Serialize(ApiKeyConstraints.Empty with
|
||||
{
|
||||
BrowseSubtrees = ["Area1/*"],
|
||||
},
|
||||
}),
|
||||
CreatedUtc: DateTimeOffset.Parse("2026-04-28T12:00:00Z", CultureInfo.InvariantCulture),
|
||||
LastUsedUtc: null,
|
||||
RevokedUtc: null));
|
||||
@@ -310,13 +310,12 @@ public sealed class DashboardSnapshotServiceTests
|
||||
{
|
||||
using GatewayMetrics metrics = new();
|
||||
SequencedApiKeyAdminStore apiKeyAdminStore = new(
|
||||
new ApiKeyRecord(
|
||||
new ApiKeyListItem(
|
||||
KeyId: "operator01",
|
||||
KeyPrefix: "mxgw_operator01",
|
||||
SecretHash: [1, 2, 3],
|
||||
KeyPrefix: "mxgw",
|
||||
DisplayName: "Operator",
|
||||
Scopes: new HashSet<string>([GatewayScopes.MetadataRead], StringComparer.Ordinal),
|
||||
Constraints: ApiKeyConstraints.Empty,
|
||||
ConstraintsJson: null,
|
||||
CreatedUtc: DateTimeOffset.Parse("2026-04-28T12:00:00Z", CultureInfo.InvariantCulture),
|
||||
LastUsedUtc: null,
|
||||
RevokedUtc: null));
|
||||
@@ -425,63 +424,56 @@ public sealed class DashboardSnapshotServiceTests
|
||||
private class FakeApiKeyAdminStore : IApiKeyAdminStore
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public Task CreateAsync(ApiKeyCreateRequest request, CancellationToken cancellationToken)
|
||||
public Task CreateAsync(ApiKeyRecord record, CancellationToken ct)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual Task<IReadOnlyList<ApiKeyRecord>> ListAsync(CancellationToken cancellationToken)
|
||||
public virtual Task<IReadOnlyList<ApiKeyListItem>> ListAsync(CancellationToken ct)
|
||||
{
|
||||
return Task.FromResult<IReadOnlyList<ApiKeyRecord>>([]);
|
||||
return Task.FromResult<IReadOnlyList<ApiKeyListItem>>([]);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<bool> RevokeAsync(
|
||||
string keyId,
|
||||
DateTimeOffset revokedUtc,
|
||||
CancellationToken cancellationToken)
|
||||
public Task<bool> RevokeAsync(string keyId, DateTimeOffset whenUtc, CancellationToken ct)
|
||||
{
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<bool> RotateAsync(
|
||||
string keyId,
|
||||
byte[] secretHash,
|
||||
DateTimeOffset rotatedUtc,
|
||||
CancellationToken cancellationToken)
|
||||
public Task<bool> RotateAsync(string keyId, byte[] newSecretHash, CancellationToken ct)
|
||||
{
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<bool> DeleteAsync(string keyId, CancellationToken cancellationToken)
|
||||
public Task<bool> DeleteAsync(string keyId, CancellationToken ct)
|
||||
{
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
}
|
||||
|
||||
private class CountingApiKeyAdminStore(params ApiKeyRecord[] records) : FakeApiKeyAdminStore
|
||||
private class CountingApiKeyAdminStore(params ApiKeyListItem[] records) : FakeApiKeyAdminStore
|
||||
{
|
||||
/// <summary>Gets the count of list operations performed.</summary>
|
||||
public int ListCount { get; protected set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Task<IReadOnlyList<ApiKeyRecord>> ListAsync(CancellationToken cancellationToken)
|
||||
public override Task<IReadOnlyList<ApiKeyListItem>> ListAsync(CancellationToken ct)
|
||||
{
|
||||
ListCount++;
|
||||
return Task.FromResult<IReadOnlyList<ApiKeyRecord>>(records);
|
||||
return Task.FromResult<IReadOnlyList<ApiKeyListItem>>(records);
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class SequencedApiKeyAdminStore(ApiKeyRecord record) : CountingApiKeyAdminStore(record)
|
||||
private sealed class SequencedApiKeyAdminStore(ApiKeyListItem record) : CountingApiKeyAdminStore(record)
|
||||
{
|
||||
/// <summary>Gets or sets a value indicating whether the next list operation should fail.</summary>
|
||||
public bool FailNext { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Task<IReadOnlyList<ApiKeyRecord>> ListAsync(CancellationToken cancellationToken)
|
||||
public override Task<IReadOnlyList<ApiKeyListItem>> ListAsync(CancellationToken ct)
|
||||
{
|
||||
if (FailNext)
|
||||
{
|
||||
@@ -490,7 +482,7 @@ public sealed class DashboardSnapshotServiceTests
|
||||
throw new InvalidOperationException("Simulated SQLite failure.");
|
||||
}
|
||||
|
||||
return base.ListAsync(cancellationToken);
|
||||
return base.ListAsync(ct);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user