Changed code to support older Python versions
This commit is contained in:
parent
eb92d2d36f
commit
582458cdd0
5027 changed files with 794942 additions and 4 deletions
|
|
@ -0,0 +1,124 @@
|
|||
import base64
|
||||
import binascii
|
||||
import json
|
||||
import logging
|
||||
import time
|
||||
from typing import Optional
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
from fastapi_cloud_cli.utils.pydantic_compat import model_dump_json, model_validate_json
|
||||
|
||||
from .config import get_auth_path
|
||||
|
||||
logger = logging.getLogger("fastapi_cli")
|
||||
|
||||
|
||||
class AuthConfig(BaseModel):
|
||||
access_token: str
|
||||
|
||||
|
||||
def write_auth_config(auth_data: AuthConfig) -> None:
|
||||
auth_path = get_auth_path()
|
||||
logger.debug("Writing auth config to: %s", auth_path)
|
||||
|
||||
auth_path.write_text(model_dump_json(auth_data), encoding="utf-8")
|
||||
logger.debug("Auth config written successfully")
|
||||
|
||||
|
||||
def delete_auth_config() -> None:
|
||||
auth_path = get_auth_path()
|
||||
logger.debug("Deleting auth config at: %s", auth_path)
|
||||
|
||||
if auth_path.exists():
|
||||
auth_path.unlink()
|
||||
logger.debug("Auth config deleted successfully")
|
||||
else:
|
||||
logger.debug("Auth config file doesn't exist, nothing to delete")
|
||||
|
||||
|
||||
def read_auth_config() -> Optional[AuthConfig]:
|
||||
auth_path = get_auth_path()
|
||||
logger.debug("Reading auth config from: %s", auth_path)
|
||||
|
||||
if not auth_path.exists():
|
||||
logger.debug("Auth config file doesn't exist")
|
||||
return None
|
||||
|
||||
logger.debug("Auth config loaded successfully")
|
||||
return model_validate_json(AuthConfig, auth_path.read_text(encoding="utf-8"))
|
||||
|
||||
|
||||
def get_auth_token() -> Optional[str]:
|
||||
logger.debug("Getting auth token")
|
||||
auth_data = read_auth_config()
|
||||
|
||||
if auth_data is None:
|
||||
logger.debug("No auth data found")
|
||||
return None
|
||||
|
||||
logger.debug("Auth token retrieved successfully")
|
||||
return auth_data.access_token
|
||||
|
||||
|
||||
def is_token_expired(token: str) -> bool:
|
||||
try:
|
||||
parts = token.split(".")
|
||||
|
||||
if len(parts) != 3:
|
||||
logger.debug("Invalid JWT format: expected 3 parts, got %d", len(parts))
|
||||
return True
|
||||
|
||||
payload = parts[1]
|
||||
|
||||
# Add padding if needed (JWT uses base64url encoding without padding)
|
||||
if padding := len(payload) % 4:
|
||||
payload += "=" * (4 - padding)
|
||||
|
||||
payload = payload.replace("-", "+").replace("_", "/")
|
||||
decoded_bytes = base64.b64decode(payload)
|
||||
payload_data = json.loads(decoded_bytes)
|
||||
|
||||
exp = payload_data.get("exp")
|
||||
|
||||
if exp is None:
|
||||
logger.debug("No 'exp' claim found in token")
|
||||
|
||||
return False
|
||||
|
||||
if not isinstance(exp, int): # pragma: no cover
|
||||
logger.debug("Invalid 'exp' claim: expected int, got %s", type(exp))
|
||||
|
||||
return True
|
||||
|
||||
current_time = time.time()
|
||||
|
||||
is_expired = current_time >= exp
|
||||
|
||||
logger.debug(
|
||||
"Token expiration check: current=%d, exp=%d, expired=%s",
|
||||
current_time,
|
||||
exp,
|
||||
is_expired,
|
||||
)
|
||||
|
||||
return is_expired
|
||||
except (binascii.Error, json.JSONDecodeError) as e:
|
||||
logger.debug("Error parsing JWT token: %s", e)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def is_logged_in() -> bool:
|
||||
token = get_auth_token()
|
||||
|
||||
if token is None:
|
||||
logger.debug("Login status: False (no token)")
|
||||
return False
|
||||
|
||||
if is_token_expired(token):
|
||||
logger.debug("Login status: False (token expired)")
|
||||
return False
|
||||
|
||||
logger.debug("Login status: True")
|
||||
return True
|
||||
Loading…
Add table
Add a link
Reference in a new issue