update main.py
kaasislekker
This commit is contained in:
+36
-1
@@ -6,7 +6,14 @@ from dotenv import load_dotenv
|
|||||||
import os
|
import os
|
||||||
from fastapi import Depends
|
from fastapi import Depends
|
||||||
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
|
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
|
||||||
from email_service import create_verification, send_verification_email
|
from email_service import (
|
||||||
|
create_verification,
|
||||||
|
send_verification_email,
|
||||||
|
send_password_reset_email,
|
||||||
|
create_password_reset,
|
||||||
|
)
|
||||||
|
|
||||||
|
import secrets
|
||||||
|
|
||||||
security = HTTPBearer()
|
security = HTTPBearer()
|
||||||
load_dotenv()
|
load_dotenv()
|
||||||
@@ -235,3 +242,31 @@ def delete_me(user_id, password):
|
|||||||
return {
|
return {
|
||||||
"status": "deleted"
|
"status": "deleted"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def reset_password(email: str):
|
||||||
|
email = email.strip().lower()
|
||||||
|
|
||||||
|
user = fetch_one(
|
||||||
|
"""
|
||||||
|
SELECT id
|
||||||
|
FROM users
|
||||||
|
WHERE email = ?
|
||||||
|
""",
|
||||||
|
(email,),
|
||||||
|
)
|
||||||
|
|
||||||
|
if user is None:
|
||||||
|
return {
|
||||||
|
"status": "sent",
|
||||||
|
}
|
||||||
|
|
||||||
|
token = create_password_reset(user["id"])
|
||||||
|
|
||||||
|
send_password_reset_email(
|
||||||
|
email,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"status": "sent",
|
||||||
|
}
|
||||||
@@ -269,3 +269,95 @@ If you did not request this, you can ignore this email.
|
|||||||
smtp_password,
|
smtp_password,
|
||||||
)
|
)
|
||||||
smtp.send_message(message)
|
smtp.send_message(message)
|
||||||
|
|
||||||
|
def send_password_reset_email(email: str, token: str):
|
||||||
|
smtp_host = os.getenv("SMTP_HOST")
|
||||||
|
smtp_port = int(os.getenv("SMTP_PORT", "587"))
|
||||||
|
smtp_username = os.getenv("SMTP_USERNAME")
|
||||||
|
smtp_password = os.getenv("SMTP_PASSWORD")
|
||||||
|
smtp_from = os.getenv("SMTP_FROM")
|
||||||
|
|
||||||
|
if not all([
|
||||||
|
smtp_host,
|
||||||
|
smtp_username,
|
||||||
|
smtp_password,
|
||||||
|
smtp_from,
|
||||||
|
]):
|
||||||
|
raise RuntimeError("SMTP configuration is incomplete")
|
||||||
|
|
||||||
|
password_reset_url = (
|
||||||
|
f"https://ben.de-roo.org/api/update-password?token={token}"
|
||||||
|
)
|
||||||
|
|
||||||
|
message = EmailMessage()
|
||||||
|
|
||||||
|
message["From"] = smtp_from
|
||||||
|
message["To"] = email
|
||||||
|
message["Subject"] = "Reset your password"
|
||||||
|
|
||||||
|
message.set_content(
|
||||||
|
f"""Hello,
|
||||||
|
|
||||||
|
You requested to use this email address for reseting your Calendar password.
|
||||||
|
|
||||||
|
Reset your password using this link:
|
||||||
|
|
||||||
|
{password_reset_url}
|
||||||
|
|
||||||
|
This link expires after 24 hours.
|
||||||
|
|
||||||
|
If you did not request this, you can ignore this email.
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
with smtplib.SMTP(smtp_host, smtp_port) as smtp:
|
||||||
|
smtp.starttls()
|
||||||
|
smtp.login(
|
||||||
|
smtp_username,
|
||||||
|
smtp_password,
|
||||||
|
)
|
||||||
|
smtp.send_message(message)
|
||||||
|
|
||||||
|
def create_password_reset(user_id: int):
|
||||||
|
token = secrets.token_urlsafe(32)
|
||||||
|
token_hash = hash_token(token)
|
||||||
|
|
||||||
|
expires_at = (
|
||||||
|
datetime.now(timezone.utc)
|
||||||
|
+ timedelta(hours=1)
|
||||||
|
).isoformat()
|
||||||
|
|
||||||
|
conn = get_connection()
|
||||||
|
cur = conn.cursor()
|
||||||
|
|
||||||
|
try:
|
||||||
|
cur.execute(
|
||||||
|
"""
|
||||||
|
DELETE FROM password_reset_tokens
|
||||||
|
WHERE user_id = ?
|
||||||
|
""",
|
||||||
|
(user_id,),
|
||||||
|
)
|
||||||
|
|
||||||
|
cur.execute(
|
||||||
|
"""
|
||||||
|
INSERT INTO password_reset_tokens (
|
||||||
|
user_id,
|
||||||
|
token_hash,
|
||||||
|
expires_at
|
||||||
|
)
|
||||||
|
VALUES (?, ?, ?)
|
||||||
|
""",
|
||||||
|
(
|
||||||
|
user_id,
|
||||||
|
token_hash,
|
||||||
|
expires_at,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
|
return token
|
||||||
|
|
||||||
|
finally:
|
||||||
|
conn.close()
|
||||||
@@ -37,6 +37,21 @@ CREATE TABLE IF NOT EXISTS email_verifications (
|
|||||||
""")
|
""")
|
||||||
|
|
||||||
|
|
||||||
|
cur.execute("""
|
||||||
|
CREATE TABLE IF NOT EXISTS password_reset_tokens (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
user_id INTEGER NOT NULL,
|
||||||
|
token_hash TEXT NOT NULL UNIQUE,
|
||||||
|
expires_at TEXT NOT NULL,
|
||||||
|
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
|
||||||
|
FOREIGN KEY (user_id)
|
||||||
|
REFERENCES users(id)
|
||||||
|
ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
""")
|
||||||
|
|
||||||
|
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
CREATE TABLE IF NOT EXISTS rooms (
|
CREATE TABLE IF NOT EXISTS rooms (
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
@@ -155,32 +170,43 @@ CREATE INDEX IF NOT EXISTS idx_room_members_user
|
|||||||
ON room_members(user_id);
|
ON room_members(user_id);
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
CREATE INDEX IF NOT EXISTS idx_events_room
|
CREATE INDEX IF NOT EXISTS idx_events_room
|
||||||
ON events(room_id);
|
ON events(room_id);
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
CREATE INDEX IF NOT EXISTS idx_event_invitations_user
|
CREATE INDEX IF NOT EXISTS idx_event_invitations_user
|
||||||
ON event_invitations(user_id);
|
ON event_invitations(user_id);
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
CREATE INDEX IF NOT EXISTS idx_event_invitations_event
|
CREATE INDEX IF NOT EXISTS idx_event_invitations_event
|
||||||
ON event_invitations(event_id);
|
ON event_invitations(event_id);
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
CREATE INDEX IF NOT EXISTS idx_event_signups_user
|
CREATE INDEX IF NOT EXISTS idx_event_signups_user
|
||||||
ON event_signups(user_id);
|
ON event_signups(user_id);
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
CREATE INDEX IF NOT EXISTS idx_email_verifications_user
|
CREATE INDEX IF NOT EXISTS idx_email_verifications_user
|
||||||
ON email_verifications(user_id);
|
ON email_verifications(user_id);
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
|
||||||
|
cur.execute("""
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_password_reset_tokens_user
|
||||||
|
ON password_reset_tokens(user_id);
|
||||||
|
""")
|
||||||
|
|
||||||
|
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
|
||||||
print("Database initialized.")
|
print("Database initialized.")
|
||||||
|
|||||||
Reference in New Issue
Block a user