Files
wx-win-agent/node-agent/WxAgent.Core/RemoteAccountContext.cs
T
rogee e8abb15f68
Build web service image / build (push) Successful in 1m6s
fix: authorize verified offline data sync
2026-09-30 13:30:48 +08:00

82 lines
3.3 KiB
C#

namespace WxAgent.Core;
public sealed record RemoteAccountIdentity(string AccountId, bool Verified);
public sealed record RemoteAccountContextSnapshot(
string? ActiveAccountId,
long Revision,
bool Confirmed);
public sealed class RemoteAccountContext
{
private readonly object _gate = new();
private RemoteAccountContextSnapshot _snapshot = new(null, 0, false);
public RemoteAccountContextSnapshot Snapshot
{
get { lock (_gate) return _snapshot; }
}
public static string? SelectActiveAccountId(
bool uiSessionAvailable,
string? preferredAccountId,
IReadOnlyCollection<RemoteAccountIdentity> identities,
IReadOnlyCollection<string> liveBoundAccountIds)
{
ArgumentNullException.ThrowIfNull(identities);
ArgumentNullException.ThrowIfNull(liveBoundAccountIds);
if (!uiSessionAvailable) return null;
var liveBoundIds = liveBoundAccountIds.ToHashSet(StringComparer.OrdinalIgnoreCase);
var eligible = identities
.Where(identity => identity.Verified && liveBoundIds.Contains(identity.AccountId))
.ToArray();
if (!string.IsNullOrWhiteSpace(preferredAccountId))
{
var preferred = eligible.FirstOrDefault(identity =>
string.Equals(identity.AccountId, preferredAccountId, StringComparison.OrdinalIgnoreCase));
if (preferred is not null) return preferred.AccountId;
}
return eligible.Length == 1 ? eligible[0].AccountId : null;
}
public RemoteAccountContextSnapshot SwitchTo(
string accountId,
IReadOnlyCollection<RemoteAccountIdentity> identities,
bool hasInFlightWrites = false)
{
RemoteAgentOptions.ValidateIdentifier(accountId, "accountId", 200);
ArgumentNullException.ThrowIfNull(identities);
lock (_gate)
{
if (hasInFlightWrites && !string.Equals(_snapshot.ActiveAccountId, accountId, StringComparison.Ordinal))
throw new WxAgentException(WxAgentErrorCode.InvalidOperationState, "Account switching is blocked while a write operation is in flight.");
var matches = identities.Where(identity => string.Equals(identity.AccountId, accountId, StringComparison.Ordinal)).ToArray();
if (matches.Length != 1 || !matches[0].Verified)
{
_snapshot = new RemoteAccountContextSnapshot(null, checked(_snapshot.Revision + 1), false);
throw new WxAgentException(WxAgentErrorCode.AccountContextUnconfirmed, "The requested account identity could not be confirmed.");
}
if (_snapshot.Confirmed && string.Equals(_snapshot.ActiveAccountId, accountId, StringComparison.Ordinal))
return _snapshot;
_snapshot = new RemoteAccountContextSnapshot(accountId, checked(_snapshot.Revision + 1), true);
return _snapshot;
}
}
public void Invalidate()
{
lock (_gate)
{
if (!_snapshot.Confirmed && _snapshot.ActiveAccountId is null) return;
_snapshot = new RemoteAccountContextSnapshot(null, checked(_snapshot.Revision + 1), false);
}
}
public bool IsConfirmedFor(string accountId)
{
lock (_gate)
return _snapshot.Confirmed && string.Equals(_snapshot.ActiveAccountId, accountId, StringComparison.Ordinal);
}
}