Initial commit

This commit is contained in:
root
2026-07-01 17:58:05 +03:00
commit 104ae25f2c
18 changed files with 1585 additions and 0 deletions

75
auth.py Normal file
View File

@@ -0,0 +1,75 @@
from __future__ import annotations
import base64
import hmac
import hashlib
import os
import time
from dataclasses import dataclass
from typing import Optional
COOKIE_NAME = "voley_admin"
def _get_secret() -> bytes:
secret = os.getenv("SECRET_KEY", "").strip()
if not secret:
# Разрешаем запуск без секрета, но с сильно сниженной безопасностью.
# Для реального деплоя SECRET_KEY обязателен.
secret = "dev-unsafe-secret"
return secret.encode("utf-8")
def _b64url(b: bytes) -> str:
return base64.urlsafe_b64encode(b).decode("ascii").rstrip("=")
def _b64url_decode(s: str) -> bytes:
pad = "=" * (-len(s) % 4)
return base64.urlsafe_b64decode((s + pad).encode("ascii"))
def _sign(payload: bytes) -> str:
mac = hmac.new(_get_secret(), payload, hashlib.sha256).digest()
return _b64url(mac)
def make_session(ttl_seconds: int = 60 * 60 * 12) -> str:
exp = int(time.time()) + int(ttl_seconds)
payload = f"exp={exp}".encode("utf-8")
sig = _sign(payload)
return f"{_b64url(payload)}.{sig}"
def verify_session(token: str) -> bool:
try:
payload_b64, sig = token.split(".", 1)
payload = _b64url_decode(payload_b64)
except Exception:
return False
if not hmac.compare_digest(_sign(payload), sig):
return False
try:
parts = payload.decode("utf-8").split("=", 1)
if len(parts) != 2 or parts[0] != "exp":
return False
exp = int(parts[1])
except Exception:
return False
return time.time() < exp
def check_admin_password(password: str) -> bool:
expected = os.getenv("ADMIN_PASSWORD", "")
if not expected:
# Чтобы админка не осталась открытой по умолчанию.
return False
return hmac.compare_digest(password or "", expected)
@dataclass(frozen=True)
class AdminAuth:
is_admin: bool
token: Optional[str] = None