Skip to main content

alibi_api/plugins/api_key/
cleanup.rs

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