revocation.rs 54 lignes · 1906 octets
//! SeaORM-backed implementation of
//! [`RemoteIdentityRevocationChecker`](rustwarden_core::middleware::revocation::RemoteIdentityRevocationChecker).
//!
//! Queries `remote_identities.disabled_at` for the given identifier and
//! returns `true` when the row is disabled. Database errors and missing
//! rows are treated as "not revoked" so a transient outage does not
//! lock every federated user out of the application.

use async_trait::async_trait;
use sea_orm::{DatabaseConnection, EntityTrait};
use uuid::Uuid;

use rustwarden_core::middleware::revocation::RemoteIdentityRevocationChecker;

use crate::models::remote_identity;

/// Default revocation checker backed by the `remote_identities` table.
///
/// Injected as `Arc<dyn RemoteIdentityRevocationChecker>` Tower
/// `Extension` from [`crate::routes::router`] when the federation
/// stack is mounted on a Rustwarden builder.
#[derive(Clone)]
pub struct SeaOrmRemoteIdentityRevocationChecker {
    /// Database handle used to look up the `remote_identities` row.
    pub db: DatabaseConnection,
}

impl SeaOrmRemoteIdentityRevocationChecker {
    /// Wrap a `DatabaseConnection` into a revocation checker.
    pub fn new(db: DatabaseConnection) -> Self {
        Self { db }
    }
}

#[async_trait]
impl RemoteIdentityRevocationChecker for SeaOrmRemoteIdentityRevocationChecker {
    async fn is_revoked(&self, remote_identity_id: Uuid) -> bool {
        match remote_identity::Entity::find_by_id(remote_identity_id)
            .one(&self.db)
            .await
        {
            Ok(Some(row)) => row.disabled_at.is_some(),
            Ok(None) => false,
            Err(err) => {
                tracing::warn!(
                    "SeaOrmRemoteIdentityRevocationChecker: lookup failed for {}: {}",
                    remote_identity_id,
                    err
                );
                false
            }
        }
    }
}