12
12
from bcrypt import gensalt , hashpw , checkpw
13
13
from datetime import UTC , datetime , timedelta
14
14
from typing import Optional
15
+ from jinja2 .environment import Template
16
+ from fastapi .templating import Jinja2Templates
15
17
from fastapi import Depends , Cookie , HTTPException , status
16
18
from utils .db import get_session
17
19
from utils .models import User , Role , PasswordResetToken
18
20
19
21
load_dotenv ()
20
- logger = logging .getLogger ("uvicorn.error" )
22
+ resend .api_key = os .environ ["RESEND_API_KEY" ]
23
+
24
+ logger = logging .getLogger (__name__ )
25
+ logger .setLevel (logging .DEBUG )
26
+ logger .addHandler (logging .StreamHandler ())
21
27
22
28
23
29
# --- Constants ---
24
30
25
31
32
+ templates = Jinja2Templates (directory = "templates" )
26
33
SECRET_KEY = os .getenv ("SECRET_KEY" )
27
34
ALGORITHM = "HS256"
28
35
ACCESS_TOKEN_EXPIRE_MINUTES = 30
@@ -294,9 +301,9 @@ def generate_password_reset_url(email: str, token: str) -> str:
294
301
return f"{ base_url } /auth/reset_password?email={ email } &token={ token } "
295
302
296
303
297
- def send_reset_email (email : str , session : Session ):
304
+ def send_reset_email (email : str , session : Session ) -> None :
298
305
# Check for an existing unexpired token
299
- user = session .exec (select (User ).where (
306
+ user : Optional [ User ] = session .exec (select (User ).where (
300
307
User .email == email
301
308
)).first ()
302
309
if user :
@@ -314,17 +321,24 @@ def send_reset_email(email: str, session: Session):
314
321
return
315
322
316
323
# Generate a new token
317
- token = str (uuid .uuid4 ())
318
- reset_token = PasswordResetToken (user_id = user .id , token = token )
324
+ token : str = str (uuid .uuid4 ())
325
+ reset_token : PasswordResetToken = PasswordResetToken (
326
+ user_id = user .id , token = token )
319
327
session .add (reset_token )
320
328
321
329
try :
322
- reset_url = generate_password_reset_url (email , token )
330
+ reset_url : str = generate_password_reset_url (email , token )
331
+
332
+ # Render the email template
333
+ template : Template = templates .get_template (
334
+ "emails/reset_email.html" )
335
+ html_content : str = template .render ({"reset_url" : reset_url })
336
+
323
337
params : resend .Emails .SendParams = {
324
338
325
339
"to" : [email ],
326
340
"subject" : "Password Reset Request" ,
327
- "html" : f"<p>Click <a href=' { reset_url } '>here</a> to reset your password.</p>" ,
341
+ "html" : html_content ,
328
342
}
329
343
330
344
sent_email : resend .Email = resend .Emails .send (params )
0 commit comments