update main.py

kaasislekker
This commit is contained in:
ben
2026-08-18 17:17:58 +02:00
parent d4be4933f8
commit 4fac3f91b6
2 changed files with 91 additions and 1 deletions
+65 -1
View File
@@ -1,7 +1,7 @@
from database import execute, fetch_one, fetch_all from database import execute, fetch_one, fetch_all
import bcrypt import bcrypt
from jose import jwt from jose import jwt
from datetime import datetime, timedelta from datetime import datetime, timedelta, timezone
from dotenv import load_dotenv from dotenv import load_dotenv
import os import os
from fastapi import Depends from fastapi import Depends
@@ -10,6 +10,7 @@ from email_service import (
create_verification, create_verification,
send_password_reset_email, send_password_reset_email,
create_password_reset, create_password_reset,
hash_token,
) )
import secrets import secrets
@@ -269,3 +270,66 @@ def reset_password(email: str):
return { return {
"status": "sent", "status": "sent",
} }
def reset_password_with_token(token: str, new_password: str):
token_hash = hash_token(token)
reset = fetch_one(
"""
SELECT id, user_id, expires_at
FROM password_reset_tokens
WHERE token_hash = ?
""",
(token_hash,),
)
if reset is None:
return {
"status": "failed",
"reason": "invalid_token",
}
expires_at = datetime.fromisoformat(reset["expires_at"])
if datetime.now(timezone.utc) >= expires_at:
execute(
"""
DELETE FROM password_reset_tokens
WHERE id = ?
""",
(reset["id"],),
)
return {
"status": "failed",
"reason": "token_expired",
}
password_hash = bcrypt.hashpw(
new_password.encode(),
bcrypt.gensalt(),
).decode()
execute(
"""
UPDATE users
SET password_hash = ?
WHERE id = ?
""",
(
password_hash,
reset["user_id"],
),
)
execute(
"""
DELETE FROM password_reset_tokens
WHERE id = ?
""",
(reset["id"],),
)
return {
"status": "updated",
}
+26
View File
@@ -30,6 +30,7 @@ from auth import (
change_password, change_password,
delete_me, delete_me,
reset_password, reset_password,
reset_password_with_token,
) )
from permissions import ( from permissions import (
@@ -126,6 +127,10 @@ class RoomCreate(BaseModel):
class ForgotPassword(BaseModel): class ForgotPassword(BaseModel):
email: EmailStr email: EmailStr
class PasswordReset(BaseModel):
token: str
new_password: str = Field(min_length=8)
class RoomSearch(BaseModel): class RoomSearch(BaseModel):
invite_code: str invite_code: str
@@ -1134,6 +1139,27 @@ def api_forgot_password(
): ):
return reset_password(data.email) return reset_password(data.email)
@app.post(
"/update-password",
summary="Reset password with token",
description="Sets a new password using a password reset token.",
)
def api_update_password(
data: PasswordReset,
):
result = reset_password_with_token(
data.token,
data.new_password,
)
if result["status"] == "failed":
raise HTTPException(
status_code=400,
detail=result["reason"],
)
return result
# easter egg # easter egg
@app.get( @app.get(