TorbatYar/backend/shared-lib/shared/security.py
Mortezakoohjani 800b0ba2c5 Deploy TorbatYar for torbatyar.ir with nginx multi-tenant routing.
Wire production domain, CORS for tenant subdomains, celery volume mounts, and nginx reverse proxy configs for apex, API, identity, auth, and wildcard tenants.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-21 21:43:33 +03:30

56 lines
1.9 KiB
Python

"""ابزارهای امنیتی مشترک بین سرویس‌ها.
شامل ساختار کاربر جاری، اسکوپ توکن‌های داخلی و توابع hash کردن توکن.
منطق تولید/اعتبارسنجی JWT کاربر در هر سرویس (core.security) پیاده می‌شود.
"""
from __future__ import annotations
import hashlib
import hmac
import secrets
from dataclasses import dataclass, field
def hash_token(token: str, *, secret: str) -> str:
"""تولید hash امن برای ذخیره توکن‌های داخلی سرویس.
توکن خام هرگز در دیتابیس ذخیره نمی‌شود؛ فقط hash آن نگهداری می‌شود.
"""
return hmac.new(secret.encode("utf-8"), token.encode("utf-8"), hashlib.sha256).hexdigest()
def verify_token(token: str, token_hash: str, *, secret: str) -> bool:
"""مقایسه امن (constant-time) توکن خام با hash ذخیره‌شده."""
expected = hash_token(token, secret=secret)
return hmac.compare_digest(expected, token_hash)
def generate_token(length: int = 48) -> str:
"""تولید توکن تصادفی امن به‌صورت URL-safe."""
return secrets.token_urlsafe(length)
@dataclass
class CurrentUser:
"""کاربر احراز هویت‌شده جاری (از JWT استخراج می‌شود)."""
user_id: str
username: str | None = None
email: str | None = None
roles: list[str] = field(default_factory=list)
tenant_id: str | None = None
def has_role(self, role: str) -> bool:
return role in self.roles
@dataclass
class InternalServiceIdentity:
"""هویت یک سرویس داخلی که با InternalServiceToken احراز شده است."""
service_key: str
scopes: list[str] = field(default_factory=list)
def has_scope(self, scope: str) -> bool:
return "*" in self.scopes or scope in self.scopes