update main.py

kaasislekker
This commit is contained in:
ben
2026-08-18 16:46:42 +02:00
parent 5d13f1e426
commit 5b5f118057
3 changed files with 155 additions and 2 deletions
+36 -1
View File
@@ -6,7 +6,14 @@ from dotenv import load_dotenv
import os
from fastapi import Depends
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()
load_dotenv()
@@ -235,3 +242,31 @@ def delete_me(user_id, password):
return {
"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",
}
+93 -1
View File
@@ -268,4 +268,96 @@ If you did not request this, you can ignore this email.
smtp_username,
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()
+26
View File
@@ -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("""
CREATE TABLE IF NOT EXISTS rooms (
id INTEGER PRIMARY KEY AUTOINCREMENT,
@@ -155,32 +170,43 @@ CREATE INDEX IF NOT EXISTS idx_room_members_user
ON room_members(user_id);
""")
cur.execute("""
CREATE INDEX IF NOT EXISTS idx_events_room
ON events(room_id);
""")
cur.execute("""
CREATE INDEX IF NOT EXISTS idx_event_invitations_user
ON event_invitations(user_id);
""")
cur.execute("""
CREATE INDEX IF NOT EXISTS idx_event_invitations_event
ON event_invitations(event_id);
""")
cur.execute("""
CREATE INDEX IF NOT EXISTS idx_event_signups_user
ON event_signups(user_id);
""")
cur.execute("""
CREATE INDEX IF NOT EXISTS idx_email_verifications_user
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()
print("Database initialized.")