Public Access
Desktop: stop decrypting the whole keychain on a sync pass that changed nothing
This commit is contained in:
1 parent
873405e591
commit
441709f1e9
2 files changed
+59
-3
No files matched your search
@@ -6367,7 +6367,7 @@ internal sealed partial class VaultViewModel(
|
||||
{
|
||||
// Before the sync, so a vault admitted here is one of the vaults that pass then pulls. The
|
||||
// other order would show a newly shared vault as an empty one until the minute after.
|
||||
await AdmitNewVaultsAsync(server.Account, cancellationToken).ConfigureAwait(true);
|
||||
var vaultsChanged = await AdmitNewVaultsAsync(server.Account, cancellationToken).ConfigureAwait(true);
|
||||
|
||||
// Every vault this session can read, not only the one new items are filed into. A team's
|
||||
// vault that never synced would show its hosts exactly once — at the unlock that first
|
||||
@@ -6380,6 +6380,15 @@ internal sealed partial class VaultViewModel(
|
||||
// that had just failed to sync, which is exactly the lie that flag exists to prevent.
|
||||
LastSyncFailed = report.Any(vault => !vault.Succeeded);
|
||||
|
||||
if (!vaultsChanged && !MayHaveChangedTheKeychain(report))
|
||||
{
|
||||
// Nothing to redraw, so nothing is decrypted: see MayHaveChangedTheKeychain. The one thing a
|
||||
// rebuild did that still has to happen is the ago-text on each card, which is a minute older.
|
||||
RestringLastConnected();
|
||||
|
||||
return report;
|
||||
}
|
||||
|
||||
await ReloadAsync(cancellationToken).ConfigureAwait(true);
|
||||
|
||||
// Host key trust arrives with the rest of the vault, and the store the SSH handshake asks holds a
|
||||
@@ -6423,7 +6432,7 @@ internal sealed partial class VaultViewModel(
|
||||
/// this list, and doing that on every quiet pass would rebuild a menu once a minute for nothing.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
private async Task AdmitNewVaultsAsync(IAccountApi api, CancellationToken cancellationToken)
|
||||
private async Task<bool> AdmitNewVaultsAsync(IAccountApi api, CancellationToken cancellationToken)
|
||||
{
|
||||
var before = session.Vaults.Count;
|
||||
|
||||
@@ -6431,12 +6440,39 @@ internal sealed partial class VaultViewModel(
|
||||
|
||||
if (admitted == 0 && session.Vaults.Count == before)
|
||||
{
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
VaultsChanged?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>Whether a pass could have left the keychain different from the lists on screen.</summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// Every pass used to end by reading the whole keychain back — decrypting every host, key, password,
|
||||
/// bucket and snippet and rebuilding every list from them — once a minute, whether or not a single item
|
||||
/// had moved. Almost every pass moves nothing, so almost all of that was spent redrawing what was already
|
||||
/// drawn.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// ◆ Conservative on purpose. A failed vault counts as changed, because a pull can apply a page and then
|
||||
/// fail on the next one, and a report with no counts is no evidence that nothing landed. Log entries do
|
||||
/// not count — a machine reads back the ones it just wrote, and nothing on these lists is drawn from the
|
||||
/// log; see <see cref="SyncReport.PulledItems"/>.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
private static bool MayHaveChangedTheKeychain(IReadOnlyList<VaultSyncReport> report) =>
|
||||
report.Any(vault => vault.Report is not { } pass
|
||||
|| pass.PulledItems > 0
|
||||
|| pass.PushedItems > 0
|
||||
|| pass.Merged > 0
|
||||
|| pass.Resurrected > 0
|
||||
|| pass.DeletesAbandoned > 0
|
||||
|| pass.Parked > 0
|
||||
|| pass.ResyncedFromStart);
|
||||
|
||||
/// <summary>
|
||||
/// Raised when a synchronisation pass found that the vaults this account can reach have changed.
|
||||
/// </summary>
|
||||
|
||||
Reference in new issue
Block a user