Skip to content

Commit

Permalink
+password changed email
Browse files Browse the repository at this point in the history
  • Loading branch information
logerzerox committed Jan 8, 2025
1 parent 5d91432 commit 9f6868a
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 0 deletions.
10 changes: 10 additions & 0 deletions py/core/base/providers/email.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class EmailConfig(ProviderConfig):
reset_password_template_id: Optional[str] = None
frontend_url: Optional[str] = None
sender_name: Optional[str] = None
password_changed_template_id: Optional[str] = None

@property
def supported_providers(self) -> list[str]:
Expand Down Expand Up @@ -74,3 +75,12 @@ async def send_password_reset_email(
self, to_email: str, reset_token: str, *args, **kwargs
) -> None:
pass

@abstractmethod
async def send_password_changed_email(
self,
to_email: str,
*args,
**kwargs,
) -> None:
pass
21 changes: 21 additions & 0 deletions py/core/providers/auth/r2r_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,14 @@ async def change_password(
id=user.id,
new_hashed_password=hashed_new_password,
)

try:
await self.email_provider.send_password_change_notification(
user.email, {"first_name": user.name.split(" ")[0]}
)
except Exception as e:
logger.error(f"Failed to send password change notification: {str(e)}")

return {"message": "Password changed successfully"}

async def request_password_reset(self, email: str) -> dict[str, str]:
Expand Down Expand Up @@ -447,9 +455,22 @@ async def confirm_password_reset(
id=user_id,
new_hashed_password=hashed_new_password,
)

await self.database_provider.users_handler.remove_reset_token(
id=user_id
)

# Get the user information
user = await self.database_provider.users_handler.get_user_by_id(
id=user_id
)
logger.info(user)
try:
await self.email_provider.send_password_changed_email(
user.email, {"first_name": user.name.split(" ")[0]}
)
except Exception as e:
logger.error(f"Failed to send password change notification: {str(e)}")
return {"message": "Password reset successfully"}

async def logout(self, token: str) -> dict[str, str]:
Expand Down
16 changes: 16 additions & 0 deletions py/core/providers/email/console_mock.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,19 @@ async def send_password_reset_email(
-----------------------------
"""
)

async def send_password_changed_email(
self, to_email: str, *args, **kwargs
) -> None:
logger.info(
f"""
-------- Email Message --------
To: {to_email}
Subject: Your Password Has Been Changed
Body:
Your password has been successfully changed.
For security reasons, you will need to log in again on all your devices.
-----------------------------
"""
)
47 changes: 47 additions & 0 deletions py/core/providers/email/sendgrid.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ def __init__(self, config: EmailConfig):
config.reset_password_template_id
or os.getenv("SENDGRID_RESET_TEMPLATE_ID")
)
self.password_changed_template_id = (
config.password_changed_template_id
or os.getenv("SENDGRID_PASSWORD_CHANGED_TEMPLATE_ID")
)
self.client = SendGridAPIClient(api_key=self.api_key)
self.sender_name = config.sender_name

Expand Down Expand Up @@ -208,3 +212,46 @@ async def send_password_reset_email(
)
logger.error(error_msg)
raise RuntimeError(error_msg) from e

async def send_password_changed_email(
self,
to_email: str,
dynamic_template_data: Optional[dict] = None,
*args,
**kwargs
) -> None:
try:
if hasattr(self, 'password_changed_template_id') and self.password_changed_template_id:
await self.send_email(
to_email=to_email,
template_id=self.password_changed_template_id,
dynamic_template_data=dynamic_template_data,
)
else:
subject = "Your Password Has Been Changed"
body = """
Your password has been successfully changed.
If you did not make this change, please contact support immediately and secure your account.
For security reasons, you will need to log in again on all your devices.
"""
html_body = """
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
<h1>Password Changed Successfully</h1>
<p>Your password has been successfully changed.</p>
<p>For security reasons, you will need to log in again on all your devices.</p>
</div>
"""
# Move send_email inside the else block
await self.send_email(
to_email=to_email,
subject=subject,
html_body=html_body,
body=body,
)
except Exception as e:
error_msg = f"Failed to send password change notification to {to_email}: {str(e)}"
logger.error(error_msg)
raise RuntimeError(error_msg) from e
29 changes: 29 additions & 0 deletions py/core/providers/email/smtp.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,3 +150,32 @@ async def send_password_reset_email(
body=body,
html_body=html_body,
)

async def send_password_changed_email(
self,
to_email: str,
*args,
**kwargs
) -> None:
body = """
Your password has been successfully changed.
If you did not make this change, please contact support immediately and secure your account.
For security reasons, you will need to log in again on all your devices.
"""

html_body = """
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
<h1>Password Changed Successfully</h1>
<p>Your password has been successfully changed.</p>
<p>For security reasons, you will need to log in again on all your devices.</p>
</div>
"""

await self.send_email(
to_email=to_email,
subject="Your Password Has Been Changed",
body=body,
html_body=html_body,
)

0 comments on commit 9f6868a

Please sign in to comment.