Skip to content

Commit bbd869f

Browse files
0xPoeTurbo87
authored andcommitted
feat: send emails
1 parent f21673c commit bbd869f

File tree

1 file changed

+38
-7
lines changed

1 file changed

+38
-7
lines changed

src/worker/jobs/expiry_notification.rs

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
use std::sync::Arc;
2-
use diesel::{Connection, PgConnection};
3-
1+
use crate::models::ApiToken;
2+
use crate::{email::Email, models::User, worker::Environment, Emails};
3+
use anyhow::anyhow;
44
use crates_io_worker::BackgroundJob;
5-
use crate::Emails;
6-
use crate::worker::Environment;
5+
use diesel::{
6+
dsl::now, Connection, ExpressionMethods, NullableExpressionMethods, PgConnection, RunQueryDsl,
7+
};
8+
use std::sync::Arc;
79

810
/// The threshold in days for the expiry notification.
911
const EXPIRY_THRESHOLD: i64 = 3;
@@ -34,18 +36,47 @@ impl BackgroundJob for CheckAboutToExpireToken {
3436
// Check if the token is about to expire and send a notification if it is.
3537
fn check(emails: &Emails, conn: &mut PgConnection) -> anyhow::Result<()> {
3638
info!("Checking if tokens are about to expire");
37-
let expired_tokens =
38-
crate::models::token::ApiToken::find_tokens_expiring_within_days(conn, EXPIRY_THRESHOLD)?;
39+
let expired_tokens = ApiToken::find_tokens_expiring_within_days(conn, EXPIRY_THRESHOLD)?;
3940
// Batch send notifications in transactions.
4041
const BATCH_SIZE: usize = 100;
4142
for chunk in expired_tokens.chunks(BATCH_SIZE) {
4243
conn.transaction(|conn| {
4344
for token in chunk {
4445
// Send notification.
46+
let user = User::find(conn, token.user_id)?;
47+
let Some(recipient) = user.email(conn)? else {
48+
return Err(anyhow!("No address found"));
49+
};
50+
let email = ExpiryNotificationEmail {
51+
token_name: token.name.clone(),
52+
expiry_date: token.expired_at.unwrap().date().to_string(),
53+
};
54+
emails.send(&recipient, email)?;
55+
// Also update the token to prevent duplicate notifications.
56+
diesel::update(token)
57+
.set(crate::schema::api_tokens::expiry_notification_at.eq(now.nullable()))
58+
.execute(conn)?;
4559
}
4660
Ok::<_, anyhow::Error>(())
4761
})?;
4862
}
4963

5064
Ok(())
5165
}
66+
67+
#[derive(Debug, Clone)]
68+
struct ExpiryNotificationEmail {
69+
token_name: String,
70+
expiry_date: String,
71+
}
72+
73+
impl Email for ExpiryNotificationEmail {
74+
const SUBJECT: &'static str = "Token Expiry Notification";
75+
76+
fn body(&self) -> String {
77+
format!(
78+
"The token {} is about to expire on {}. Please take action.",
79+
self.token_name, self.expiry_date
80+
)
81+
}
82+
}

0 commit comments

Comments
 (0)