To_DO: ERROR AFTER LOGGING IN
This commit is contained in:
0
utils/__init__.py
Normal file
0
utils/__init__.py
Normal file
43
utils/auth_decorators.py
Normal file
43
utils/auth_decorators.py
Normal file
@@ -0,0 +1,43 @@
|
||||
from functools import wraps
|
||||
from flask import session, redirect, url_for, flash, request
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def login_required(f):
|
||||
"""
|
||||
Decorator to protect routes that require authentication
|
||||
"""
|
||||
@wraps(f)
|
||||
def decorated_function(*args, **kwargs):
|
||||
if 'user_id' not in session or 'email' not in session:
|
||||
flash('Please log in to access this page', 'warning')
|
||||
logger.info(f"Unauthorized access attempt to {request.endpoint}")
|
||||
return redirect(url_for('login'))
|
||||
return f(*args, **kwargs)
|
||||
return decorated_function
|
||||
|
||||
def logout_required(f):
|
||||
"""
|
||||
Decorator for routes that should only be accessible when NOT logged in
|
||||
(e.g., login, register pages)
|
||||
"""
|
||||
@wraps(f)
|
||||
def decorated_function(*args, **kwargs):
|
||||
if 'user_id' in session:
|
||||
flash('You are already logged in', 'info')
|
||||
return redirect(url_for('dashboard'))
|
||||
return f(*args, **kwargs)
|
||||
return decorated_function
|
||||
|
||||
def get_current_user():
|
||||
"""
|
||||
Helper function to get current user info from session
|
||||
"""
|
||||
if 'user_id' in session:
|
||||
return {
|
||||
'id': session['user_id'],
|
||||
'username': session['username'],
|
||||
'email': session['email']
|
||||
}
|
||||
return None
|
||||
27
utils/password_utils.py
Normal file
27
utils/password_utils.py
Normal file
@@ -0,0 +1,27 @@
|
||||
import hashlib
|
||||
import secrets
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class PasswordUtils:
|
||||
@staticmethod
|
||||
def hash_password(password: str, salt: str = None) -> tuple[str, str]:
|
||||
if salt is None:
|
||||
salt = secrets.token_hex(32)
|
||||
password = password.strip()
|
||||
salted_password = password + salt
|
||||
hash_object = hashlib.sha512(salted_password.encode('utf-8'))
|
||||
password_hash = hash_object.hexdigest()
|
||||
logger.debug("Password hashed successfully")
|
||||
return password_hash, salt
|
||||
|
||||
@staticmethod
|
||||
def verify_password(password: str, stored_hash: str, salt: str) -> bool:
|
||||
computed_hash, _ = PasswordUtils.hash_password(password, salt)
|
||||
return secrets.compare_digest(computed_hash, stored_hash)
|
||||
|
||||
@staticmethod
|
||||
def hash_password_simple(password: str) -> str:
|
||||
password = password.strip()
|
||||
return hashlib.sha512(password.encode('utf-8')).hexdigest()
|
||||
56
utils/validation.py
Normal file
56
utils/validation.py
Normal file
@@ -0,0 +1,56 @@
|
||||
import re
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class ValidationUtils:
|
||||
@staticmethod
|
||||
def validate_email(email: str) -> bool:
|
||||
if not email or not isinstance(email, str):
|
||||
return False
|
||||
|
||||
email = email.strip().lower()
|
||||
pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
|
||||
is_valid = bool(re.match(pattern, email))
|
||||
|
||||
if not is_valid:
|
||||
logger.warning(f"Invalid email format: {email}")
|
||||
|
||||
return is_valid
|
||||
|
||||
@staticmethod
|
||||
def validate_username(username: str) -> bool:
|
||||
if not username or not isinstance(username, str):
|
||||
return False
|
||||
username = username.strip()
|
||||
# Username-Regeln: 3-25 Zeichen, nur Buchstaben, Zahlen und Unterstrich
|
||||
if len(username) < 3 or len(username) > 25:
|
||||
logger.warning(f"Username length invalid: {len(username)}")
|
||||
return False
|
||||
pattern = r'^[a-zA-Z0-9_]+$'
|
||||
is_valid = bool(re.match(pattern, username))
|
||||
if not is_valid:
|
||||
logger.warning(f"Invalid username format: {username}")
|
||||
return is_valid
|
||||
|
||||
@staticmethod
|
||||
def validate_password(password: str) -> tuple[bool, list[str]]:
|
||||
errors = []
|
||||
if not password or not isinstance(password, str):
|
||||
errors.append("Password is required")
|
||||
return False, errors
|
||||
if len(password) < 4 or len(password) > 50:
|
||||
errors.append("Password must be at least 4 characters long and must not exceed 128 characters")
|
||||
if not re.search(r'[A-Z]', password):
|
||||
errors.append("Password must contain at least one uppercase letter")
|
||||
if not re.search(r'[a-z]', password):
|
||||
errors.append("Password must contain at least one lowercase letter")
|
||||
if not re.search(r'\d', password):
|
||||
errors.append("Password must contain at least one digit")
|
||||
if not re.search(r'[!@#$%^&*(),.?":{}|<>]', password):
|
||||
errors.append("Password must contain at least one special character")
|
||||
is_valid = len(errors) == 0
|
||||
if not is_valid:
|
||||
logger.warning(f"Password validation failed: {errors}")
|
||||
|
||||
return is_valid, errors
|
||||
Reference in New Issue
Block a user