Skip to main content

alibi_plugins/api_key/
cleanup.rs

1use super::types::DeleteExpiredApiKeysResponse;
2use super::{ApiKeyConfig, ApiKeyPlugin, admit_expired_cleanup};
3use alibi_core::{AuthContext, AuthResult};
4use std::sync::Arc;
5impl ApiKeyPlugin {
6    /// Start automatic cleanup without awaiting its deletion.
7    pub(super) async fn maybe_delete_expired(
8        &self,
9        ctx: &AuthContext<impl alibi_core::AuthSchema>,
10    ) -> AuthResult<()> {
11        _ = self.start_configured_cleanup(ctx).await?;
12        Ok(())
13    }
14
15    pub(super) async fn register_expired_cleanup(
16        &self,
17        ctx: &AuthContext<impl alibi_core::AuthSchema>,
18    ) -> AuthResult<()> {
19        let completion = self.start_configured_cleanup(ctx).await?;
20        if let Some(handler) = &ctx.config.background_tasks {
21            handler.handle(completion)
22        } else {
23            drop(completion);
24            Ok(())
25        }
26    }
27
28    pub(super) async fn start_configured_cleanup(
29        &self,
30        ctx: &AuthContext<impl alibi_core::AuthSchema>,
31    ) -> AuthResult<alibi_core::BackgroundTaskCompletion> {
32        if self.configurations.iter().any(ApiKeyConfig::uses_database) {
33            Self::start_expired_cleanup(ctx).await
34        } else {
35            Ok(Box::pin(async { Ok(()) }))
36        }
37    }
38
39    pub(super) async fn start_expired_cleanup(
40        ctx: &AuthContext<impl alibi_core::AuthSchema>,
41    ) -> AuthResult<alibi_core::BackgroundTaskCompletion> {
42        if !admit_expired_cleanup(false) {
43            return Ok(Box::pin(async { Ok(()) }));
44        }
45        let database = Arc::clone(&ctx.database);
46        Self::start_background_work(async move {
47            if let Err(error) = database.delete_expired_api_keys().await {
48                tracing::error!(%error, "Failed to delete expired API keys");
49            }
50            Ok(())
51        })
52        .await
53    }
54
55    // Both automatic bulk cleanup and deferred single-row rejection own their
56    // work before application completion registration, preserving hook context.
57    pub(super) async fn start_background_work(
58        operation: impl Future<Output = AuthResult<()>> + Send + 'static,
59    ) -> AuthResult<alibi_core::BackgroundTaskCompletion> {
60        alibi_core::start_background_task(operation).await
61    }
62
63    /// Force cleanup across owners/configurations, updating the same global
64    /// automatic-cleanup timestamp and awaiting deletion despite the throttle.
65    pub async fn delete_all_expired_api_keys(
66        &self,
67        ctx: &AuthContext<impl alibi_core::AuthSchema>,
68    ) -> DeleteExpiredApiKeysResponse {
69        _ = admit_expired_cleanup(true);
70        if !self.configurations.iter().any(ApiKeyConfig::uses_database) {
71            return DeleteExpiredApiKeysResponse {
72                success: true,
73                error: None,
74            };
75        }
76        if let Err(error) = ctx.database.delete_expired_api_keys().await {
77            tracing::error!(%error, "Failed to delete expired API keys");
78        }
79        DeleteExpiredApiKeysResponse {
80            success: true,
81            error: None,
82        }
83    }
84}