mirror of
https://github.com/sudosylabs/vnidrop.git
synced 2026-08-12 05:29:57 +02:00
fix(core): tear down shares on forget/block and fail-closed blocks
Cancel targeted protocol shares synchronously before await, and treat block lookup errors as denied so store failures cannot admit blocked peers. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -183,7 +183,7 @@ impl ApprovalService {
|
||||
.contacts()
|
||||
.is_blocked(&remote_endpoint_id)
|
||||
.await
|
||||
.unwrap_or(false)
|
||||
.unwrap_or(true)
|
||||
{
|
||||
// Indistinguishable from other refusals so probing cannot detect blocks.
|
||||
return self
|
||||
|
||||
@@ -129,10 +129,11 @@ impl DeviceRelationshipService {
|
||||
}
|
||||
|
||||
pub(super) async fn is_blocked(&self, endpoint_id: &str) -> bool {
|
||||
// Fail closed: a store error must not admit blocked traffic.
|
||||
self.contacts()
|
||||
.is_blocked(endpoint_id)
|
||||
.await
|
||||
.unwrap_or(false)
|
||||
.unwrap_or(true)
|
||||
}
|
||||
|
||||
/// Drop orphaned relationship grant secrets and disable rows whose secrets are gone.
|
||||
|
||||
@@ -86,7 +86,7 @@ impl CoreInner {
|
||||
.contacts()
|
||||
.is_blocked(&peer_endpoint_id)
|
||||
.await
|
||||
.unwrap_or(false)
|
||||
.unwrap_or(true)
|
||||
{
|
||||
return Ok(false);
|
||||
}
|
||||
@@ -103,7 +103,7 @@ impl CoreInner {
|
||||
.device_relationships
|
||||
.forget(peer_endpoint_id.clone())
|
||||
.await?;
|
||||
// Targeted transfers for this relationship only (ticket 10 fills in).
|
||||
// Targeted transfers for this relationship only.
|
||||
// Invitation-domain shares are deliberately not cancelled here.
|
||||
self.cancel_targeted_transfers_for_peer(&peer_endpoint_id)
|
||||
.await?;
|
||||
|
||||
@@ -62,6 +62,17 @@ impl CoreInner {
|
||||
.push(peer_endpoint_id.to_string());
|
||||
}
|
||||
self.targeted_offers.discard_from(peer_endpoint_id).await;
|
||||
let protocol_ids = self
|
||||
.targeted_store()
|
||||
.protocol_ids_for_peer(peer_endpoint_id)
|
||||
.await?;
|
||||
// Signal active transfers synchronously before awaiting share teardown.
|
||||
for protocol_transfer_id in &protocol_ids {
|
||||
let _ = self.take_active_transfer(*protocol_transfer_id);
|
||||
}
|
||||
for protocol_transfer_id in &protocol_ids {
|
||||
let _ = self.cancel_idle_or_share(*protocol_transfer_id).await;
|
||||
}
|
||||
self.targeted_store().cancel_by_peer(peer_endpoint_id).await
|
||||
}
|
||||
|
||||
|
||||
@@ -187,10 +187,6 @@ impl TargetedOfferInbox {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(
|
||||
dead_code,
|
||||
reason = "called via cancel_targeted_transfers_for_peer for ticket 09"
|
||||
)]
|
||||
pub(crate) async fn discard_from(&self, endpoint_id: &str) {
|
||||
let ids: Vec<String> = {
|
||||
let pending = self.pending.lock().await;
|
||||
|
||||
@@ -159,10 +159,6 @@ impl TargetedTransferStore {
|
||||
rows.into_iter().map(row_to_transfer).collect()
|
||||
}
|
||||
|
||||
#[allow(
|
||||
dead_code,
|
||||
reason = "called via cancel_targeted_transfers_for_peer for ticket 09"
|
||||
)]
|
||||
pub(crate) async fn cancel_by_peer(&self, peer_endpoint_id: &str) -> Result<u64, VnidropError> {
|
||||
let now = now_ms();
|
||||
let result = sqlx::query(
|
||||
@@ -180,6 +176,26 @@ impl TargetedTransferStore {
|
||||
.map_err(VnidropError::repository)?;
|
||||
Ok(result.rows_affected())
|
||||
}
|
||||
|
||||
pub(crate) async fn protocol_ids_for_peer(
|
||||
&self,
|
||||
peer_endpoint_id: &str,
|
||||
) -> Result<Vec<u64>, VnidropError> {
|
||||
let rows = sqlx::query(
|
||||
r#"
|
||||
SELECT protocol_transfer_id FROM targeted_transfers
|
||||
WHERE sender_endpoint_id = ?1 OR receiver_endpoint_id = ?1
|
||||
"#,
|
||||
)
|
||||
.bind(peer_endpoint_id)
|
||||
.fetch_all(&self.pool)
|
||||
.await
|
||||
.map_err(VnidropError::repository)?;
|
||||
Ok(rows
|
||||
.into_iter()
|
||||
.map(|row| row.get::<i64, _>(0) as u64)
|
||||
.collect())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
||||
Reference in New Issue
Block a user