shared/application/auth/
reset_password_service.rs1use crate::error::Result;
2
3use crate::domain::model::{ExpiringLink, PasswordResetToken};
4use crate::intern::auth::AuthService;
5
6impl AuthService {
7 #[tracing::instrument(name = "auth.insert_password_reset_token", skip(self, user_id))]
8 pub async fn insert_password_reset_token(&self, user_id: &str) -> Result<ExpiringLink> {
9 let token = self.crypto.token.generate()?;
11 let hashed_token = self.crypto.token.hash(&token);
12
13 let expiry_timestamp = chrono::Utc::now()
15 + chrono::Duration::seconds(self.configuration.auth.password.reset.token_expires_in);
16
17 let password_reset_token = PasswordResetToken::default()
18 .with_user_id(user_id)
19 .with_token_hash(&hashed_token)
20 .with_expiray(&expiry_timestamp);
21
22 self.password_reset_token_repository
23 .insert(password_reset_token)
24 .await?;
25
26 let link = format!(
27 "{}/auth/password/reset?token={}",
28 self.configuration.app.url, &token
29 );
30
31 Ok(ExpiringLink {
32 link,
33 expires_at: expiry_timestamp,
34 })
35 }
36
37 #[tracing::instrument(name = "auth.validate_reset_password_token", skip(self, token))]
38 pub async fn validate_reset_password_token(&self, token: &str) -> Result<PasswordResetToken> {
39 let hash = self.crypto.token.hash(token);
40
41 self.password_reset_token_repository.consume(&hash).await
42 }
43
44 #[tracing::instrument(name = "auth.invalidate_password_reset_token", skip(self, id))]
45 pub async fn invalidate_password_reset_token(&self, id: &str) -> Result<PasswordResetToken> {
46 self.password_reset_token_repository.invalidate(id).await
47 }
48
49 #[tracing::instrument(
50 name = "auth.revoke_password_reset_token", skip(self), fields(user.id = user_id)
51 )]
52 pub async fn revoke_password_reset_token(&self, user_id: &str) -> Result<()> {
53 self.password_reset_token_repository.revoke(user_id).await
54 }
55}