// lib/services/auth/auth_interceptor.dart // // یک wrapper کوچک که قبل/بعد از هر درخواست API: // - مطمئن می‌شود `RequestService.token` با access token جاری همگام است. // - اگر access token در آستانه‌ی انقضا است، قبل از درخواست refresh می‌کند. // - در صورت دریافت 401 برای یک درخواست، یک‌بار refresh کرده و درخواست را // مجددا اجرا می‌کند. // // این فایل عمدا lightweight است و به ساختار فعلی RequestService وابسته است // تا کمترین تغییر در سرویس‌های دیگر اعمال شود. import 'package:didvan/services/auth/keycloak_auth_service.dart'; import 'package:didvan/services/auth/token_storage.dart'; import 'package:didvan/services/network/request.dart'; class AuthInterceptor { AuthInterceptor._(); /// قبل از هر درخواست شبکه‌ی نیازمند احراز هویت اجرا می‌شود. /// /// اگر access token در دسترس نیست یا نزدیک به انقضاست، تلاش می‌کنیم /// با refresh token تمدید کنیم. static Future ensureFreshToken() async { if (TokenStorage.isAccessTokenValid) { // فقط RequestService.token را sync می‌کنیم. RequestService.token = TokenStorage.accessToken; return; } // ignore: avoid_print print('🔐 ensureFreshToken: access invalid -> attempting refresh ' '(hasRefresh=${TokenStorage.refreshToken != null})'); if (TokenStorage.refreshToken != null) { await KeycloakAuthService.instance.refresh(); } RequestService.token = TokenStorage.accessToken; } /// در صورت دریافت 401، یک‌بار تلاش به refresh می‌کنیم. /// اگر موفق شد true برمی‌گرداند تا فراخواننده درخواست را retry کند. static Future handleUnauthorized() async { if (TokenStorage.refreshToken == null) return false; final ok = await KeycloakAuthService.instance.refresh(); if (ok) { RequestService.token = TokenStorage.accessToken; } return ok; } }