from django.conf import settings from django.core import signing from rest_framework.authentication import BaseAuthentication from rest_framework.exceptions import AuthenticationFailed from .models import User ACCESS_TOKEN_SALT = 'tadrisino-access-token' def issue_access_token(user_id: int) -> str: """ ساخت access token امضاشده (stateless) — دیتابیس ذخیره نمی‌شه، فقط امضا و expiry داره. با django.core.signing (بدون نیاز به کتابخونه‌ی JWT). """ signer = signing.TimestampSigner(salt=ACCESS_TOKEN_SALT) return signer.sign(str(user_id)) def decode_access_token(token: str) -> int: signer = signing.TimestampSigner(salt=ACCESS_TOKEN_SALT) try: value = signer.unsign(token, max_age=settings.ACCESS_TOKEN_TTL_SECONDS) except signing.SignatureExpired: raise AuthenticationFailed('توکن منقضی شده است.') except signing.BadSignature: raise AuthenticationFailed('توکن نامعتبر است.') return int(value) class TadrisinoTokenAuthentication(BaseAuthentication): """ هدر مورد انتظار: Authorization: Bearer اگه هدر نباشه، درخواست به‌صورت anonymous ادامه پیدا می‌کنه (None, None) و View خودش تصمیم می‌گیره که آیا auth اجباریه (IsAuthenticated) یا نه. """ keyword = 'Bearer' def authenticate(self, request): auth_header = request.headers.get('Authorization', '') if not auth_header: return None parts = auth_header.split() if len(parts) != 2 or parts[0] != self.keyword: return None token = parts[1] user_id = decode_access_token(token) try: user = User.objects.get(pk=user_id) except User.DoesNotExist: raise AuthenticationFailed('کاربر پیدا نشد.') return (user, token) def authenticate_header(self, request): return self.keyword