File size: 2,072 Bytes
a8a2cf5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import logging
from fastapi import Depends, HTTPException, status 
from datetime import datetime, timedelta
from jwt import encode
from .config.config import settings

# Use bcrypt directly instead of passlib for compatibility
try:
    import bcrypt
    BCRYPT_AVAILABLE = True
except ImportError:
    BCRYPT_AVAILABLE = False

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

def hash_password(password: str) -> str:
    """Hash a password using bcrypt."""
    if not BCRYPT_AVAILABLE:
        logger.warning("bcrypt not available - using plaintext passwords (INSECURE!)")
        return password
    # Truncate password to 72 bytes (bcrypt limit) and encode to bytes
    truncated = password[:72].encode('utf-8')
    salt = bcrypt.gensalt()
    hashed = bcrypt.hashpw(truncated, salt)
    return hashed.decode('utf-8')

def verify_password(plain_password: str, hashed_password: str) -> bool:
    """Verify a password against its hash."""
    if not BCRYPT_AVAILABLE:
        logger.warning("bcrypt not available - using plaintext comparison (INSECURE!)")
        return plain_password == hashed_password
    # Truncate password to 72 bytes (bcrypt limit) and encode to bytes
    truncated = plain_password[:72].encode('utf-8')
    hashed_bytes = hashed_password.encode('utf-8')
    return bcrypt.checkpw(truncated, hashed_bytes)

def create_access_token(user_id: int, email: str) -> str:
    """Create a JWT access token."""
    to_encode = {
        "sub": str(user_id),
        "email": email,
        "exp": datetime.utcnow() + timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)
    }
    encoded_jwt = encode(to_encode, settings.SECRET_KEY, algorithm=settings.JWT_ALGORITHM)
    return encoded_jwt

def get_database():
    """
    This function is a helper function to simulate getting a database connection.
    Dependencies are like workers who prepare things for you.
    """
    logger.info("Creating the database connection...")
    try:
        yield None
    finally:
        logger.info("Closing the database connection...")