40 lines
1.1 KiB
Python
40 lines
1.1 KiB
Python
from datetime import datetime, timedelta, timezone
|
|
from typing import Optional
|
|
|
|
import bcrypt
|
|
import jwt
|
|
|
|
from config import settings
|
|
|
|
BCRYPT_ROUNDS = 12
|
|
|
|
|
|
def _truncate(pw: str) -> bytes:
|
|
return pw.encode("utf-8")[:72]
|
|
|
|
|
|
def hash_password(password: str) -> str:
|
|
return bcrypt.hashpw(_truncate(password), bcrypt.gensalt(rounds=BCRYPT_ROUNDS)).decode()
|
|
|
|
|
|
def verify_password(plain: str, hashed: str) -> bool:
|
|
try:
|
|
return bcrypt.checkpw(_truncate(plain), hashed.encode())
|
|
except (ValueError, TypeError):
|
|
return False
|
|
|
|
|
|
def create_access_token(subject: str | int, extra: Optional[dict] = None) -> str:
|
|
now = datetime.now(timezone.utc)
|
|
payload = {
|
|
"sub": str(subject),
|
|
"iat": int(now.timestamp()),
|
|
"exp": int((now + timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)).timestamp()),
|
|
}
|
|
if extra:
|
|
payload.update(extra)
|
|
return jwt.encode(payload, settings.SECRET_KEY, algorithm=settings.ALGORITHM)
|
|
|
|
|
|
def decode_token(token: str) -> dict:
|
|
return jwt.decode(token, settings.SECRET_KEY, algorithms=[settings.ALGORITHM])
|