webfingerd/tests/test_reaper.rs

90 lines
2.9 KiB
Rust

mod common;
use webfingerd::reaper;
#[tokio::test]
async fn test_reaper_expires_links() {
let state = common::test_state().await;
// Insert a resource + link that expires immediately
use sea_orm::*;
use webfingerd::auth;
use webfingerd::entity::{domains, links, resources, service_tokens};
let now = chrono::Utc::now().naive_utc();
let past = now - chrono::Duration::seconds(60);
// Create domain
let domain = domains::ActiveModel {
id: Set("d1".into()),
domain: Set("example.com".into()),
owner_token_hash: Set(auth::hash_token("test").unwrap()),
registration_secret: Set(String::new()),
challenge_type: Set("dns-01".into()),
challenge_token: Set(None),
verified: Set(true),
created_at: Set(now),
verified_at: Set(Some(now)),
};
domain.insert(&state.db).await.unwrap();
// Create service token
let token = service_tokens::ActiveModel {
id: Set("t1".into()),
domain_id: Set("d1".into()),
name: Set("test".into()),
token_hash: Set(auth::hash_token("test").unwrap()),
allowed_rels: Set(r#"["self"]"#.into()),
resource_pattern: Set("acct:*@example.com".into()),
created_at: Set(now),
revoked_at: Set(None),
};
token.insert(&state.db).await.unwrap();
// Create resource
let resource = resources::ActiveModel {
id: Set("r1".into()),
domain_id: Set("d1".into()),
resource_uri: Set("acct:alice@example.com".into()),
aliases: Set(None),
properties: Set(None),
created_at: Set(now),
updated_at: Set(now),
};
resource.insert(&state.db).await.unwrap();
// Create expired link
let link = links::ActiveModel {
id: Set("l1".into()),
resource_id: Set("r1".into()),
service_token_id: Set("t1".into()),
domain_id: Set("d1".into()),
rel: Set("self".into()),
href: Set(Some("https://example.com/users/alice".into())),
link_type: Set(None),
titles: Set(None),
properties: Set(None),
template: Set(None),
ttl_seconds: Set(Some(1)),
created_at: Set(past),
expires_at: Set(Some(past + chrono::Duration::seconds(1))),
};
link.insert(&state.db).await.unwrap();
// Hydrate cache
state.cache.hydrate(&state.db).await.unwrap();
// Should NOT be in cache (already expired)
assert!(state.cache.get("acct:alice@example.com").is_none());
// Run reaper once
reaper::reap_once(&state.db, &state.cache).await.unwrap();
// Link should be deleted from DB
let remaining = links::Entity::find().all(&state.db).await.unwrap();
assert!(remaining.is_empty());
// Orphaned resource should also be cleaned up
let remaining_resources = resources::Entity::find().all(&state.db).await.unwrap();
assert!(remaining_resources.is_empty());
}