headless_lms_models/
user_email_codes.rs1use crate::prelude::*;
2
3#[derive(sqlx::FromRow, Debug, Clone)]
4pub struct UserEmailCode {
5 pub id: Uuid,
6 pub user_id: Uuid,
7 pub code: String,
8 pub expires_at: DateTime<Utc>,
9 pub used_at: Option<DateTime<Utc>>,
10 pub created_at: DateTime<Utc>,
11 pub updated_at: DateTime<Utc>,
12 pub deleted_at: Option<DateTime<Utc>>,
13}
14
15pub async fn insert_user_email_code(
16 conn: &mut PgConnection,
17 user_id: Uuid,
18 code: String,
19) -> ModelResult<String> {
20 let mut tx = conn.begin().await?;
21
22 let _ = sqlx::query!(
24 r#"
25 UPDATE user_email_codes
26SET deleted_at = NOW()
27WHERE user_id = $1
28 AND deleted_at IS NULL
29 "#,
30 user_id
31 )
32 .execute(&mut *tx)
33 .await?;
34
35 let record = sqlx::query!(
37 r#"
38 INSERT INTO user_email_codes (code, user_id)
39VALUES ($1, $2)
40RETURNING *
41 "#,
42 code,
43 user_id
44 )
45 .fetch_one(&mut *tx)
46 .await?;
47
48 tx.commit().await?;
49
50 Ok(record.code)
51}
52
53pub async fn get_unused_user_email_code_with_user_id(
54 conn: &mut PgConnection,
55 user_id: Uuid,
56) -> ModelResult<Option<UserEmailCode>> {
57 let now = Utc::now();
58 let record = sqlx::query_as!(
59 UserEmailCode,
60 r#"
61SELECT *
62FROM user_email_codes
63WHERE user_id = $1
64 AND deleted_at IS NULL
65 AND used_at IS NULL
66 AND expires_at > $2
67 "#,
68 user_id,
69 now
70 )
71 .fetch_optional(conn)
72 .await?;
73
74 Ok(record)
75}
76
77pub async fn is_reset_user_email_code_valid(
78 conn: &mut PgConnection,
79 user_id: Uuid,
80 code: &String,
81) -> ModelResult<bool> {
82 let now = Utc::now();
83 let record = sqlx::query!(
84 r#"
85SELECT *
86FROM user_email_codes
87WHERE user_id = $1
88 AND code = $2
89 AND deleted_at IS NULL
90 AND used_at IS NULL
91 AND expires_at > $3
92 "#,
93 user_id,
94 code,
95 now
96 )
97 .fetch_optional(conn)
98 .await?;
99
100 Ok(record.is_some())
101}
102
103pub async fn mark_user_email_code_used(
104 conn: &mut PgConnection,
105 user_id: Uuid,
106 code: &str,
107) -> ModelResult<bool> {
108 let result = sqlx::query!(
109 r#"
110UPDATE user_email_codes
111SET used_at = NOW(),
112 deleted_at = NOW()
113WHERE user_id = $1
114 AND code = $2
115 AND deleted_at IS NULL
116 "#,
117 user_id,
118 code
119 )
120 .execute(conn)
121 .await?;
122
123 Ok(result.rows_affected() > 0)
124}