FEAT: Got started on the user forgot password feature as well as added error handling

This commit is contained in:
JustIceO7
2025-01-27 19:32:46 +00:00
parent 93b3ffbc0b
commit ed438e6c2f
2 changed files with 100 additions and 21 deletions

View File

@@ -1,5 +1,5 @@
from flask import Blueprint, jsonify, session from flask import Blueprint, jsonify, session
from utils.user_utils import is_subscribed, is_following, subscription_expiration from utils.user_utils import is_subscribed, is_following, subscription_expiration, verify_token, reset_password
user_bp = Blueprint("user", __name__) user_bp = Blueprint("user", __name__)
@@ -50,9 +50,23 @@ def authenticate_user() -> dict:
@user_bp.route('/forgot_password', methods=['POST']) @user_bp.route('/forgot_password', methods=['POST'])
def forgot_password(): def user_forgot_password():
""" """
Will send link to email to reset password by looking at the user_id within session to see whos password should be reset Will send link to email to reset password by looking at the user_id within session to see whos password should be reset
Creates a super random number to be used a the link to reset password I guess a random number generator seeded with a secret Creates a super random number to be used a the link to reset password I guess a random number generator seeded with a secret
""" """
return return
@user_bp.route('/reset_password/<string:token>/<string:new_password>')
def user_reset_password(token, new_password):
"""
Given token and new password resets the users password
"""
email = verify_token(token)
if email:
response = reset_password(new_password, email)
if response:
return "Success"
else:
return "Failure"
return "Failure"

View File

@@ -1,6 +1,13 @@
from database.database import Database from database.database import Database
from typing import Optional from typing import Optional
from datetime import datetime from datetime import datetime
from itsdangerous import URLSafeTimedSerializer
from os import getenv
from werkzeug.security import generate_password_hash, check_password_hash
from dotenv import load_dotenv
load_dotenv()
serializer = URLSafeTimedSerializer(getenv("AUTH_SECRET_KEY"))
def get_user_id(username: str) -> Optional[int]: def get_user_id(username: str) -> Optional[int]:
""" """
@@ -8,8 +15,16 @@ def get_user_id(username: str) -> Optional[int]:
""" """
db = Database() db = Database()
cursor = db.create_connection() cursor = db.create_connection()
data = cursor.execute("SELECT user_id FROM user WHERE username = ?", (username,)).fetchone()
try:
data = cursor.execute(
"SELECT user_id FROM user WHERE username = ?",
(username,)
).fetchone()
return data[0] if data else None return data[0] if data else None
except Exception as e:
print(f"Error: {e}")
return None
def get_username(user_id: str) -> Optional[str]: def get_username(user_id: str) -> Optional[str]:
""" """
@@ -17,27 +32,47 @@ def get_username(user_id: str) -> Optional[str]:
""" """
db = Database() db = Database()
cursor = db.create_connection() cursor = db.create_connection()
data = cursor.execute("SELECT username FROM user WHERE username = ?", (user_id,)).fetchone()
try:
data = cursor.execute(
"SELECT username FROM user WHERE user_id = ?",
(user_id,)
).fetchone()
return data[0] if data else None return data[0] if data else None
except Exception as e:
print(f"Error: {e}")
return None
def is_subscribed(user_id: int, streamer_id: int) -> bool: def is_subscribed(user_id: int, streamer_id: int) -> bool:
""" """
Returns True if user is subscribed to a streamer else False Returns True if user is subscribed to a streamer, else False
""" """
db = Database() db = Database()
cursor = db.create_connection() cursor = db.create_connection()
return bool(cursor.execute(
"SELECT 1 FROM subscribes WHERE user_id = ? AND streamer_id = ? AND expires > since", try:
(user_id, streamer_id) result = cursor.execute(
).fetchone()) "SELECT 1 FROM subscribes WHERE user_id = ? AND streamer_id = ? AND expires > ?",
(user_id, streamer_id, datetime.now())
).fetchone()
return bool(result)
except Exception as e:
print(f"Error: {e}")
return False
def is_following(user_id: int, streamer_id: int) -> bool: def is_following(user_id: int, streamer_id: int) -> bool:
db = Database() db = Database()
cursor = db.create_connection() cursor = db.create_connection()
return bool(cursor.execute(
try:
result = cursor.execute(
"SELECT 1 FROM follows WHERE user_id = ? AND streamer_id = ?", "SELECT 1 FROM follows WHERE user_id = ? AND streamer_id = ?",
(user_id, streamer_id) (user_id, streamer_id)
).fetchone()) ).fetchone()
return bool(result)
except Exception as e:
print(f"Error: {e}")
return False
def subscription_expiration(user_id: int, streamer_id: int) -> int: def subscription_expiration(user_id: int, streamer_id: int) -> int:
""" """
@@ -45,11 +80,41 @@ def subscription_expiration(user_id: int, streamer_id: int) -> int:
""" """
db = Database() db = Database()
cursor = db.create_connection() cursor = db.create_connection()
remaining_time = 0
try:
data = cursor.execute( data = cursor.execute(
"SELECT expires from subscriptions WHERE user_id = ? AND streamer_id = ? AND expires > since", (user_id,streamer_id)).fetchone() "SELECT expires from subscriptions WHERE user_id = ? AND streamer_id = ? AND expires > since", (user_id,streamer_id)).fetchone()
remaining_time = 0
if data: if data:
expiration_date = data[0] expiration_date = data[0]
remaining_time = (expiration_date - datetime.now()).seconds remaining_time = (expiration_date - datetime.now()).seconds
except Exception as e:
print(f"Error: {e}")
return remaining_time return remaining_time
def verify_token(token: str):
"""
Given a token verifies token and decodes the token into an email
"""
try:
email = serializer.loads(token, salt='1', max_age=3600)
return email
except Exception as e:
print(f"Error: {e}")
return False
def reset_password(new_password: str, email: str):
"""
Given email and new password reset the password for a given user
"""
db = Database()
cursor = db.create_connection()
try:
cursor.execute("UPDATE users SET password = ? WHERE email = ?", (generate_password_hash(new_password), email))
db.commit()
return True
except Exception as e:
print(f"Error: {e}")
return False