Authorize data sync on connected agent registration
This commit is contained in:
@@ -42,12 +42,11 @@ public sealed class RemoteAgentHostedService(
|
||||
using var client = new RemoteControlClient(remote);
|
||||
var ledger = new RemoteTaskLedger(Path.Combine(options.DataDirectory, "remote-task-ledger.json"));
|
||||
var eventQueue = remoteQueue ?? new RemoteEventQueue(Path.Combine(options.DataDirectory, "remote-event-queue.json"));
|
||||
var dataQueue = options.EnableDataSync
|
||||
? new RemoteDataBatchQueue(Path.Combine(options.DataDirectory, "remote-data-queue.json"), options.DataSyncQueueMaxItems, options.DataSyncQueueMaxBytes)
|
||||
: null;
|
||||
var syncState = options.EnableDataSync
|
||||
? new RemoteDataSyncStateStore(Path.Combine(options.DataDirectory, "remote-data-sync-state.json"))
|
||||
: null;
|
||||
// A configured Agent connection is the data-sync authorization boundary.
|
||||
// EnableDataSync remains only as a read-compatibility property for old service.json files.
|
||||
var dataQueue = new RemoteDataBatchQueue(
|
||||
Path.Combine(options.DataDirectory, "remote-data-queue.json"), options.DataSyncQueueMaxItems, options.DataSyncQueueMaxBytes);
|
||||
var syncState = new RemoteDataSyncStateStore(Path.Combine(options.DataDirectory, "remote-data-sync-state.json"));
|
||||
var blockedDataSyncAccounts = new HashSet<string>(StringComparer.Ordinal);
|
||||
var lastDataSyncAt = DateTimeOffset.MinValue;
|
||||
string? registeredActiveAccountId = null;
|
||||
@@ -66,9 +65,9 @@ public sealed class RemoteAgentHostedService(
|
||||
await DelayAsync(RetryDelay, stoppingToken);
|
||||
continue;
|
||||
}
|
||||
var reporting = runtime.Reporting;
|
||||
activeReporting = reporting;
|
||||
var snapshot = await ReadSnapshotAsync(remote, stoppingToken);
|
||||
var reporting = ConnectionAuthorizedReporting(runtime.Reporting, snapshot);
|
||||
activeReporting = reporting;
|
||||
var registrationNeedsRefresh = client.AuthState != RemoteAuthState.Authenticated
|
||||
|| !string.Equals(registeredActiveAccountId, snapshot.ActiveAccountId, StringComparison.Ordinal)
|
||||
|| registeredActiveAccountVerified != snapshot.ActiveAccountVerified
|
||||
@@ -474,8 +473,9 @@ public sealed class RemoteAgentHostedService(
|
||||
throw new ServiceException("InvalidPage", 500, "The node returned a non-advancing contact page.");
|
||||
offset = next;
|
||||
}
|
||||
var allChats = scopes.Any(scope => scope.ChatId == "*");
|
||||
var allowed = scopes.Select(scope => scope.ChatId).ToHashSet(StringComparer.Ordinal);
|
||||
var items = all.Where(contact => allowed.Contains(contact.Id)).ToArray();
|
||||
var items = allChats ? all.ToArray() : all.Where(contact => allowed.Contains(contact.Id)).ToArray();
|
||||
var matchedScopeCount = scopes.Count(scope => all.Any(contact => string.Equals(contact.Id, scope.ChatId, StringComparison.Ordinal)));
|
||||
var coverage = CreateCoverage(
|
||||
matchedScopeCount == scopes.Count
|
||||
@@ -531,6 +531,21 @@ public sealed class RemoteAgentHostedService(
|
||||
string accountId, IReadOnlyList<RemoteReportingScope> scopes, CancellationToken cancellationToken)
|
||||
{
|
||||
var contacts = new Dictionary<string, ContactInfo>(StringComparer.Ordinal);
|
||||
if (scopes.Any(scope => scope.ChatId == "*"))
|
||||
{
|
||||
for (var offset = 0; ;)
|
||||
{
|
||||
var page = await backend.ContactsAsync(accountId, null, null, 200, offset, cancellationToken);
|
||||
foreach (var contact in page.Items)
|
||||
contacts[contact.Id] = contact;
|
||||
if (!page.HasMore) break;
|
||||
var next = page.NextOffset ?? offset + page.Items.Count;
|
||||
if (next <= offset)
|
||||
throw new ServiceException("InvalidPage", 500, "The node returned a non-advancing contact page.");
|
||||
offset = next;
|
||||
}
|
||||
return contacts.Values.ToArray();
|
||||
}
|
||||
foreach (var scope in scopes)
|
||||
{
|
||||
for (var offset = 0; ;)
|
||||
@@ -556,6 +571,8 @@ public sealed class RemoteAgentHostedService(
|
||||
|
||||
private static bool SessionMatchesScope(SessionInfo session, RemoteReportingScope scope, IReadOnlyList<ContactInfo> contacts)
|
||||
{
|
||||
if (scope.ChatId == "*")
|
||||
return true;
|
||||
if (string.Equals(scope.ChatId, session.AutomationId, StringComparison.Ordinal) ||
|
||||
string.Equals(scope.ChatId, session.Name, StringComparison.Ordinal))
|
||||
return true;
|
||||
@@ -721,6 +738,29 @@ public sealed class RemoteAgentHostedService(
|
||||
}
|
||||
}
|
||||
|
||||
private static ReportingConfig ConnectionAuthorizedReporting(ReportingConfig configured, BackendSnapshot snapshot)
|
||||
{
|
||||
var accounts = snapshot.Accounts
|
||||
.Where(identity => identity.Verified)
|
||||
.Select(identity => new AccountReportingConfig
|
||||
{
|
||||
AccountId = identity.AccountId,
|
||||
Enabled = true,
|
||||
AllowedChats =
|
||||
[
|
||||
new AllowedChat { Type = ReportingChatType.Group, ChatId = "*", Enabled = true, IdentityVerified = true },
|
||||
new AllowedChat { Type = ReportingChatType.Private, ChatId = "*", Enabled = true, IdentityVerified = true }
|
||||
]
|
||||
})
|
||||
.ToArray();
|
||||
return configured with
|
||||
{
|
||||
Enabled = true,
|
||||
ConfigVersion = Math.Max(1, configured.ConfigVersion),
|
||||
Accounts = accounts
|
||||
};
|
||||
}
|
||||
|
||||
private static RemoteNodeRegistration CreateRegistration(RemoteAgentOptions remote, ReportingConfig reporting, BackendSnapshot snapshot) =>
|
||||
new(remote.NodeId!, typeof(RemoteAgentHostedService).Assembly.GetName().Version?.ToString() ?? "dev",
|
||||
RemoteProtocol.Version, ["heartbeat", "poll-tasks", "send-text", "read-sessions", "read-contacts", "read-messages", "db-messages", "db-merged", "report-message"], reporting.ConfigVersion,
|
||||
|
||||
Reference in New Issue
Block a user