File size: 3,554 Bytes
3337c5d | 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 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | """
Authrix - API Key Authentication & Usage Tracking
"""
import secrets
import hashlib
from datetime import datetime, timedelta
from typing import Optional
import json
from pathlib import Path
# Simple file-based storage (replace with database in production)
API_KEYS_FILE = Path("api_keys.json")
USAGE_FILE = Path("usage.json")
# Tier limits (analyses per month)
TIER_LIMITS = {
"free": 10,
"pro": 100,
"business": 1000,
"enterprise": 999999,
"owner": 999999, # Owner has unlimited access
}
def generate_api_key() -> str:
"""Generate a secure API key."""
return f"authrix_{secrets.token_urlsafe(32)}"
def hash_key(api_key: str) -> str:
"""Hash API key for storage."""
return hashlib.sha256(api_key.encode()).hexdigest()
def create_api_key(email: str, tier: str = "free") -> str:
"""Create a new API key for a user."""
api_key = generate_api_key()
key_hash = hash_key(api_key)
keys = load_api_keys()
keys[key_hash] = {
"email": email,
"tier": tier,
"created_at": datetime.now().isoformat(),
"active": True,
}
save_api_keys(keys)
return api_key
def validate_api_key(api_key: str) -> Optional[dict]:
"""Validate API key and return user info."""
if not api_key:
return None
key_hash = hash_key(api_key)
keys = load_api_keys()
if key_hash not in keys:
return None
key_data = keys[key_hash]
if not key_data.get("active", False):
return None
return key_data
def check_usage_limit(api_key: str) -> tuple[bool, int, int]:
"""
Check if user has exceeded their monthly limit.
Returns (allowed, used, limit).
"""
key_data = validate_api_key(api_key)
if not key_data:
return False, 0, 0
tier = key_data.get("tier", "free")
# Owner has unlimited access
if tier == "owner" or key_data.get("unlimited", False):
return True, 0, 999999
limit = TIER_LIMITS.get(tier, 10)
# Get current month usage
key_hash = hash_key(api_key)
usage = load_usage()
current_month = datetime.now().strftime("%Y-%m")
if key_hash not in usage:
usage[key_hash] = {}
used = usage[key_hash].get(current_month, 0)
return used < limit, used, limit
def increment_usage(api_key: str):
"""Increment usage counter for the current month."""
key_hash = hash_key(api_key)
usage = load_usage()
current_month = datetime.now().strftime("%Y-%m")
if key_hash not in usage:
usage[key_hash] = {}
usage[key_hash][current_month] = usage[key_hash].get(current_month, 0) + 1
save_usage(usage)
def load_api_keys() -> dict:
"""Load API keys from file."""
if not API_KEYS_FILE.exists():
return {}
return json.loads(API_KEYS_FILE.read_text())
def save_api_keys(keys: dict):
"""Save API keys to file."""
API_KEYS_FILE.write_text(json.dumps(keys, indent=2))
def load_usage() -> dict:
"""Load usage data from file."""
if not USAGE_FILE.exists():
return {}
return json.loads(USAGE_FILE.read_text())
def save_usage(usage: dict):
"""Save usage data to file."""
USAGE_FILE.write_text(json.dumps(usage, indent=2))
# Create a demo API key on first run
if not API_KEYS_FILE.exists():
demo_key = create_api_key("demo@authrix.ai", "pro")
print(f"\n🔑 Demo API Key created: {demo_key}")
print(f" Tier: Pro (100 analyses/month)")
print(f" Add to requests: X-API-Key: {demo_key}\n")
|