First Working version. I can add table
This commit is contained in:
0
src/auth/__init__.py
Normal file
0
src/auth/__init__.py
Normal file
123
src/auth/auth_manager.py
Normal file
123
src/auth/auth_manager.py
Normal file
@@ -0,0 +1,123 @@
|
||||
from typing import Optional, Dict, Any, Tuple
|
||||
|
||||
from core.user_dao import UserDAO
|
||||
|
||||
|
||||
class AuthManager:
|
||||
"""
|
||||
Authentication manager that handles user sessions and permissions.
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def login_user(session, user_data: Dict[str, Any]) -> None:
|
||||
"""
|
||||
Log in a user by setting session data.
|
||||
|
||||
Args:
|
||||
session: The session object
|
||||
user_data: User data to store in session
|
||||
"""
|
||||
# Store minimal user data in session
|
||||
session["user_id"] = user_data["id"]
|
||||
session["username"] = user_data["username"]
|
||||
session["user_email"] = user_data["email"]
|
||||
session["is_admin"] = bool(user_data["is_admin"])
|
||||
|
||||
@staticmethod
|
||||
def logout_user(session) -> None:
|
||||
"""
|
||||
Log out a user by clearing session data.
|
||||
|
||||
Args:
|
||||
session: The session object
|
||||
"""
|
||||
# Clear all user-related session data
|
||||
session.pop("user_id", None)
|
||||
session.pop("username", None)
|
||||
session.pop("user_email", None)
|
||||
session.pop("is_admin", None)
|
||||
|
||||
@staticmethod
|
||||
def get_current_user(session) -> Optional[Dict[str, Any]]:
|
||||
"""
|
||||
Get the currently logged-in user from session.
|
||||
|
||||
Args:
|
||||
session: The session object
|
||||
|
||||
Returns:
|
||||
Dict or None: User data if logged in, None otherwise
|
||||
"""
|
||||
user_id = session.get("user_id")
|
||||
if not user_id:
|
||||
return None
|
||||
|
||||
# Get full user data from database
|
||||
return UserDAO.get_user_by_id(user_id)
|
||||
|
||||
@staticmethod
|
||||
def is_authenticated(session) -> bool:
|
||||
"""
|
||||
Check if a user is authenticated.
|
||||
|
||||
Args:
|
||||
session: The session object
|
||||
|
||||
Returns:
|
||||
bool: True if authenticated, False otherwise
|
||||
"""
|
||||
return "user_id" in session
|
||||
|
||||
@staticmethod
|
||||
def is_admin(session) -> bool:
|
||||
"""
|
||||
Check if the current user is an admin.
|
||||
|
||||
Args:
|
||||
session: The session object
|
||||
|
||||
Returns:
|
||||
bool: True if admin, False otherwise
|
||||
"""
|
||||
return session.get("is_admin", False)
|
||||
|
||||
@staticmethod
|
||||
def require_auth(session) -> Tuple[bool, Optional[str]]:
|
||||
"""
|
||||
Check if authentication is required.
|
||||
|
||||
Args:
|
||||
session: The session object
|
||||
|
||||
Returns:
|
||||
Tuple[bool, Optional[str]]: (is_authorized, redirect_url)
|
||||
"""
|
||||
if not AuthManager.is_authenticated(session):
|
||||
return False, "/login"
|
||||
return True, None
|
||||
|
||||
@staticmethod
|
||||
def require_admin(session) -> Tuple[bool, Optional[str]]:
|
||||
"""
|
||||
Check if admin authentication is required.
|
||||
|
||||
Args:
|
||||
session: The session object
|
||||
|
||||
Returns:
|
||||
Tuple[bool, Optional[str]]: (is_authorized, redirect_url)
|
||||
"""
|
||||
if not AuthManager.is_authenticated(session):
|
||||
return False, "/login"
|
||||
|
||||
if not AuthManager.is_admin(session):
|
||||
return False, "/"
|
||||
|
||||
return True, None
|
||||
|
||||
@staticmethod
|
||||
def get_current_user_id(session):
|
||||
if not AuthManager.is_authenticated(session):
|
||||
return None
|
||||
|
||||
return session["user_id"]
|
||||
93
src/auth/email_auth.py
Normal file
93
src/auth/email_auth.py
Normal file
@@ -0,0 +1,93 @@
|
||||
import re
|
||||
from typing import Any
|
||||
|
||||
from core.user_dao import UserDAO
|
||||
|
||||
|
||||
class EmailAuth:
|
||||
"""
|
||||
Handles email/password authentication.
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def validate_registration(username: str, email: str, password: str, confirm_password: str) -> tuple[bool, str]:
|
||||
"""
|
||||
Validate registration input.
|
||||
|
||||
Args:
|
||||
username: The username
|
||||
email: The email address
|
||||
password: The password
|
||||
confirm_password: Password confirmation
|
||||
|
||||
Returns:
|
||||
Tuple[bool, str]: (is_valid, error_message)
|
||||
"""
|
||||
# Check username length
|
||||
if len(username) < 3 or len(username) > 30:
|
||||
return False, "Username must be between 3 and 30 characters"
|
||||
|
||||
# Check username format (letters, numbers, underscores, hyphens)
|
||||
if not re.match(r'^[a-zA-Z0-9_-]+$', username):
|
||||
return False, "Username can only contain letters, numbers, underscores, and hyphens"
|
||||
|
||||
# Check email format
|
||||
if not re.match(r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$', email):
|
||||
return False, "Invalid email format"
|
||||
|
||||
# Check password length
|
||||
if len(password) < 8:
|
||||
return False, "Password must be at least 8 characters long"
|
||||
|
||||
# Check password strength (at least one uppercase, one lowercase, one digit)
|
||||
if not (re.search(r'[A-Z]', password) and re.search(r'[a-z]', password) and re.search(r'[0-9]', password)):
|
||||
return False, "Password must contain at least one uppercase letter, one lowercase letter, and one digit"
|
||||
|
||||
# Check password match
|
||||
if password != confirm_password:
|
||||
return False, "Passwords do not match"
|
||||
|
||||
return True, ""
|
||||
|
||||
@staticmethod
|
||||
def register_user(username: str, email: str, password: str) -> tuple[bool, str, int | None]:
|
||||
"""
|
||||
Register a new user with email and password.
|
||||
|
||||
Args:
|
||||
username: The username
|
||||
email: The email address
|
||||
password: The password
|
||||
|
||||
Returns:
|
||||
Tuple[bool, str, Optional[int]]: (success, message, user_id)
|
||||
"""
|
||||
# Create user in database
|
||||
user_id = UserDAO.create_user(username=username, email=email, password=password)
|
||||
|
||||
if user_id == 0:
|
||||
return False, "Username or email already exists", None
|
||||
|
||||
return True, "Registration successful", user_id
|
||||
|
||||
@staticmethod
|
||||
def authenticate(email: str, password: str) -> tuple[bool, str, dict[str, Any] | None]:
|
||||
"""
|
||||
Authenticate a user with email and password.
|
||||
|
||||
Args:
|
||||
email: The email address
|
||||
password: The password
|
||||
|
||||
Returns:
|
||||
Tuple[bool, str, Optional[Dict]]: (success, message, user_data)
|
||||
"""
|
||||
if not email or not password:
|
||||
return False, "Email and password are required", None
|
||||
|
||||
user_data = UserDAO.authenticate_email(email, password)
|
||||
|
||||
if not user_data:
|
||||
return False, "Invalid email or password", None
|
||||
|
||||
return True, "Authentication successful", user_data
|
||||
Reference in New Issue
Block a user