mirror of
https://github.com/maxdorninger/MediaManager.git
synced 2026-04-23 17:28:42 +02:00
add feature: password resets via email
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import logging
|
||||
import os
|
||||
import uuid
|
||||
from typing import Optional
|
||||
@@ -13,13 +14,20 @@ from fastapi_users.authentication import (
|
||||
from fastapi_users.db import SQLAlchemyUserDatabase
|
||||
from httpx_oauth.clients.openid import OpenID
|
||||
from fastapi.responses import RedirectResponse, Response
|
||||
from pydantic import AnyHttpUrl
|
||||
from starlette import status
|
||||
|
||||
from media_manager.auth.config import AuthConfig, OpenIdConfig
|
||||
from media_manager.auth.config import AuthConfig, OpenIdConfig, EmailConfig
|
||||
from media_manager.auth.db import User, get_user_db
|
||||
from media_manager.auth.schemas import UserUpdate
|
||||
from media_manager.config import BasicConfig
|
||||
|
||||
import smtplib
|
||||
from email.mime.text import MIMEText
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
config = AuthConfig()
|
||||
SECRET = config.token_secret
|
||||
LIFETIME = config.session_lifetime
|
||||
@@ -47,7 +55,7 @@ class UserManager(UUIDIDMixin, BaseUserManager[User, uuid.UUID]):
|
||||
verification_token_secret = SECRET
|
||||
|
||||
async def on_after_register(self, user: User, request: Optional[Request] = None):
|
||||
print(f"User {user.id} has registered.")
|
||||
log.info(f"User {user.id} has registered.")
|
||||
if user.email in config.admin_email:
|
||||
updated_user = UserUpdate(is_superuser=True, is_verified=True)
|
||||
await self.update(user=user, user_update=updated_user)
|
||||
@@ -55,20 +63,55 @@ class UserManager(UUIDIDMixin, BaseUserManager[User, uuid.UUID]):
|
||||
async def on_after_forgot_password(
|
||||
self, user: User, token: str, request: Optional[Request] = None
|
||||
):
|
||||
print(f"User {user.id} has forgot their password. Reset token: {token}")
|
||||
link = f"{BasicConfig().FRONTEND_URL}login/reset-password?token={token}"
|
||||
log.info(f"User {user.id} has forgot their password. Reset Link: {link}")
|
||||
if not config.email_password_resets:
|
||||
log.info("Email password resets are disabled, not sending email.")
|
||||
return
|
||||
|
||||
email_conf = EmailConfig()
|
||||
subject = "MediaManager - Password Reset Request"
|
||||
html = f"""\
|
||||
<html>
|
||||
<body>
|
||||
<p>Hi {user.email},
|
||||
<br>
|
||||
<br>
|
||||
if you forgot your password, <a href="{link}">reset you password here</a>.<br>
|
||||
If you did not request a password reset, you can ignore this email.</p>
|
||||
<br>
|
||||
<br>
|
||||
If the link does not work, copy the following link into your browser: {link}<br>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
message = MIMEMultipart()
|
||||
message["From"] = email_conf.from_email
|
||||
message["To"] = user.email
|
||||
message["Subject"] = subject
|
||||
message.attach(MIMEText(html, "html"))
|
||||
|
||||
with smtplib.SMTP(email_conf.smtp_host, email_conf.smtp_port) as server:
|
||||
if email_conf.use_tls:
|
||||
server.starttls()
|
||||
server.login(email_conf.smtp_user, email_conf.smtp_password)
|
||||
server.sendmail(email_conf.from_email,user.email, message.as_string())
|
||||
log.info(f"Sent password reset email to {user.email}")
|
||||
|
||||
|
||||
async def on_after_reset_password(
|
||||
self, user: User, request: Optional[Request] = None
|
||||
):
|
||||
print(f"User {user.id} has reset their password.")
|
||||
log.info(f"User {user.id} has reset their password.")
|
||||
|
||||
async def on_after_request_verify(
|
||||
self, user: User, token: str, request: Optional[Request] = None
|
||||
):
|
||||
print(f"Verification requested for user {user.id}. Verification token: {token}")
|
||||
log.info(f"Verification requested for user {user.id}. Verification token: {token}")
|
||||
|
||||
async def on_after_verify(self, user: User, request: Optional[Request] = None):
|
||||
print(f"User {user.id} has been verified")
|
||||
log.info(f"User {user.id} has been verified")
|
||||
|
||||
|
||||
async def get_user_manager(user_db: SQLAlchemyUserDatabase = Depends(get_user_db)):
|
||||
|
||||
Reference in New Issue
Block a user