1+ use std:: collections:: BTreeMap ;
12use crate :: AppState ;
23use crate :: users:: models:: { Link , User } ;
34use axum:: extract:: { Path , State } ;
@@ -7,15 +8,21 @@ use lambda_http::tracing::info;
78use serde:: { Deserialize , Serialize } ;
89use serde_json:: json;
910use std:: sync:: Arc ;
11+ use hmac:: { Hmac , Mac } ;
12+ use jwt:: { SignWithKey , VerifyWithKey } ;
13+ use sha2:: Sha256 ;
1014use tower_http:: cors:: CorsLayer ;
1115use twilight_model:: id:: Id ;
1216use twilight_model:: id:: marker:: UserMarker ;
1317use twilight_model:: user:: CurrentUser ;
18+ use crate :: discord:: ise;
1419use crate :: guilds:: models:: Guild ;
20+ use crate :: users:: email:: send_verify_email;
1521
1622pub fn router ( ) -> axum:: Router < AppState > {
1723 axum:: Router :: new ( )
1824 . route ( "/" , post ( post_link) )
25+ . route ( "/send-email" , post ( post_send_email) )
1926 . route ( "/{link_address}" , delete ( delete_link) )
2027 . layer ( CorsLayer :: permissive ( ) )
2128}
@@ -69,7 +76,13 @@ async fn post_link(
6976 . await ?
7077 }
7178 LinkOrigin :: Email => {
72- todo ! ( ) ;
79+ let key: Hmac < Sha256 > = Hmac :: new_from_slice ( std:: env:: var ( "DISCORD_BOT_TOKEN" ) . expect ( "DISCORD_BOT_TOKEN must be set" ) . into_bytes ( ) . as_ref ( ) )
80+ . map_err ( ise) ?;
81+ let claims: BTreeMap < String , String > = link_req. token . verify_with_key ( & key) . map_err ( ise) ?;
82+ if claims. get ( "exp" ) . unwrap ( ) . parse :: < u64 > ( ) . unwrap ( ) < chrono:: Utc :: now ( ) . timestamp ( ) as u64 {
83+ return Err ( http:: StatusCode :: UNAUTHORIZED ) ;
84+ }
85+ claims. get ( "sub" ) . unwrap ( ) . to_string ( )
7386 }
7487 } ;
7588
@@ -170,3 +183,26 @@ async fn delete_link(
170183 json ! ( { "status" : "success" , "message" : "Link deleted" } ) ,
171184 ) )
172185}
186+
187+ #[ derive( Clone , Serialize , Deserialize ) ]
188+ struct SendEmailRequest {
189+ email : String ,
190+ }
191+
192+ async fn post_send_email (
193+ // Path(_user_id): Path<Id<UserMarker>>,
194+ Extension ( current_user) : Extension < CurrentUser > ,
195+ State ( app_state) : State < AppState > ,
196+ Json ( send_email_req) : Json < SendEmailRequest > ,
197+ ) -> Result < Json < serde_json:: Value > , http:: StatusCode > {
198+ let key: Hmac < Sha256 > = Hmac :: new_from_slice ( std:: env:: var ( "DISCORD_BOT_TOKEN" ) . expect ( "DISCORD_BOT_TOKEN must be set" ) . into_bytes ( ) . as_ref ( ) )
199+ . map_err ( ise) ?;
200+ let mut claims = BTreeMap :: new ( ) ;
201+ claims. insert ( "sub" , send_email_req. email . clone ( ) ) ;
202+ claims. insert ( "exp" , ( chrono:: Utc :: now ( ) + chrono:: Duration :: hours ( 1 ) ) . timestamp ( ) . to_string ( ) ) ;
203+ let token_str = claims. sign_with_key ( & key) . map_err ( ise) ?;
204+
205+ send_verify_email ( & app_state. ses , & * current_user. name , send_email_req. email , & token_str) . await ?;
206+
207+ Ok ( Json ( json ! ( { "status" : "success" } ) ) )
208+ }
0 commit comments