|
| 1 | +use crate::worker::Environment; |
| 2 | +use crates_io_database::schema::trustpub_tokens; |
| 3 | +use crates_io_worker::BackgroundJob; |
| 4 | +use diesel::prelude::*; |
| 5 | +use diesel_async::RunQueryDsl; |
| 6 | +use std::sync::Arc; |
| 7 | + |
| 8 | +/// A background job that deletes expired temporary access |
| 9 | +/// tokens from the database. |
| 10 | +#[derive(Deserialize, Serialize)] |
| 11 | +pub struct DeleteExpiredTokens; |
| 12 | + |
| 13 | +impl BackgroundJob for DeleteExpiredTokens { |
| 14 | + const JOB_NAME: &'static str = "trustpub::delete_expired_tokens"; |
| 15 | + |
| 16 | + type Context = Arc<Environment>; |
| 17 | + |
| 18 | + async fn run(&self, ctx: Self::Context) -> anyhow::Result<()> { |
| 19 | + let mut conn = ctx.deadpool.get().await?; |
| 20 | + |
| 21 | + diesel::delete(trustpub_tokens::table) |
| 22 | + .filter(trustpub_tokens::expires_at.lt(diesel::dsl::now)) |
| 23 | + .execute(&mut conn) |
| 24 | + .await?; |
| 25 | + |
| 26 | + Ok(()) |
| 27 | + } |
| 28 | +} |
| 29 | + |
| 30 | +#[cfg(test)] |
| 31 | +mod tests { |
| 32 | + use super::*; |
| 33 | + use crate::tests::util::TestApp; |
| 34 | + use chrono::{TimeDelta, Utc}; |
| 35 | + use crates_io_database::models::trustpub::NewToken; |
| 36 | + use insta::assert_compact_debug_snapshot; |
| 37 | + |
| 38 | + #[tokio::test(flavor = "multi_thread")] |
| 39 | + async fn test_expiry() -> anyhow::Result<()> { |
| 40 | + let (app, _client) = TestApp::full().empty().await; |
| 41 | + let mut conn = app.db_conn().await; |
| 42 | + |
| 43 | + let token = NewToken { |
| 44 | + expires_at: Utc::now() + TimeDelta::minutes(30), |
| 45 | + hashed_token: &[0xC0, 0xFF, 0xEE], |
| 46 | + crate_ids: &[1], |
| 47 | + }; |
| 48 | + token.insert(&mut conn).await?; |
| 49 | + |
| 50 | + let token = NewToken { |
| 51 | + expires_at: Utc::now() - TimeDelta::minutes(5), |
| 52 | + hashed_token: &[0xBA, 0xAD, 0xF0, 0x0D], |
| 53 | + crate_ids: &[2], |
| 54 | + }; |
| 55 | + token.insert(&mut conn).await?; |
| 56 | + |
| 57 | + DeleteExpiredTokens.enqueue(&mut conn).await?; |
| 58 | + app.run_pending_background_jobs().await; |
| 59 | + |
| 60 | + // Check that the expired token was deleted |
| 61 | + let crate_ids: Vec<Vec<Option<i32>>> = trustpub_tokens::table |
| 62 | + .select(trustpub_tokens::crate_ids) |
| 63 | + .load(&mut conn) |
| 64 | + .await?; |
| 65 | + |
| 66 | + assert_compact_debug_snapshot!(crate_ids, @"[[Some(1)]]"); |
| 67 | + |
| 68 | + Ok(()) |
| 69 | + } |
| 70 | +} |
0 commit comments