@@ -13,6 +13,7 @@ pub struct Email {
13
13
pub user_id : i32 ,
14
14
pub email : String ,
15
15
pub verified : bool ,
16
+ pub primary : bool ,
16
17
#[ diesel( deserialize_as = String , serialize_as = String ) ]
17
18
pub token : SecretString ,
18
19
}
@@ -24,46 +25,65 @@ pub struct NewEmail<'a> {
24
25
pub email : & ' a str ,
25
26
#[ builder( default = false ) ]
26
27
pub verified : bool ,
28
+ #[ builder( default = false ) ]
29
+ pub primary : bool ,
27
30
}
28
31
29
32
impl NewEmail < ' _ > {
30
- pub async fn insert ( & self , conn : & mut AsyncPgConnection ) -> QueryResult < ( ) > {
33
+ pub async fn insert ( & self , conn : & mut AsyncPgConnection ) -> QueryResult < Email > {
31
34
diesel:: insert_into ( emails:: table)
32
35
. values ( self )
33
- . execute ( conn)
34
- . await ?;
35
-
36
- Ok ( ( ) )
36
+ . returning ( Email :: as_returning ( ) )
37
+ . get_result ( conn)
38
+ . await
37
39
}
38
40
39
- /// Inserts the email into the database and returns the confirmation token,
40
- /// or does nothing if it already exists and returns `None`.
41
- pub async fn insert_if_missing (
41
+ /// Inserts the email into the database and returns it, unless the user already has a
42
+ /// primary email, in which case it will do nothing and return `None`.
43
+ pub async fn insert_primary_if_missing (
42
44
& self ,
43
45
conn : & mut AsyncPgConnection ,
44
- ) -> QueryResult < Option < SecretString > > {
45
- diesel:: insert_into ( emails:: table)
46
- . values ( self )
47
- . on_conflict_do_nothing ( )
48
- . returning ( emails:: token)
49
- . get_result :: < String > ( conn)
50
- . await
51
- . map ( Into :: into)
52
- . optional ( )
46
+ ) -> QueryResult < Option < Email > > {
47
+ // Check if the user already has a primary email
48
+ let primary_count = emails:: table
49
+ . filter ( emails:: user_id. eq ( self . user_id ) )
50
+ . filter ( emails:: primary. eq ( true ) )
51
+ . count ( )
52
+ . get_result :: < i64 > ( conn)
53
+ . await ?;
54
+
55
+ if primary_count > 0 {
56
+ return Ok ( None ) ; // User already has a primary email
57
+ }
58
+
59
+ self . insert ( conn) . await . map ( Some )
53
60
}
54
61
55
- pub async fn insert_or_update (
62
+ // Inserts an email for the user, replacing the primary email if it exists.
63
+ pub async fn insert_or_update_primary (
56
64
& self ,
57
65
conn : & mut AsyncPgConnection ,
58
- ) -> QueryResult < SecretString > {
59
- diesel:: insert_into ( emails:: table)
60
- . values ( self )
61
- . on_conflict ( emails:: user_id)
62
- . do_update ( )
63
- . set ( self )
64
- . returning ( emails:: token)
65
- . get_result :: < String > ( conn)
66
- . await
67
- . map ( Into :: into)
66
+ ) -> QueryResult < Email > {
67
+ // Attempt to update an existing primary email
68
+ let updated_email = diesel:: update (
69
+ emails:: table
70
+ . filter ( emails:: user_id. eq ( self . user_id ) )
71
+ . filter ( emails:: primary. eq ( true ) ) ,
72
+ )
73
+ . set ( (
74
+ emails:: email. eq ( self . email ) ,
75
+ emails:: verified. eq ( self . verified ) ,
76
+ ) )
77
+ . returning ( Email :: as_returning ( ) )
78
+ . get_result ( conn)
79
+ . await
80
+ . optional ( ) ?;
81
+
82
+ if let Some ( email) = updated_email {
83
+ return Ok ( email) ;
84
+ } else {
85
+ // Otherwise, insert a new email
86
+ self . insert ( conn) . await
87
+ }
68
88
}
69
89
}
0 commit comments