add auth
This commit is contained in:
@@ -15,7 +15,6 @@ import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:worker/core/constants/api_constants.dart';
|
||||
import 'package:worker/core/errors/exceptions.dart';
|
||||
import 'package:worker/features/auth/data/datasources/auth_local_datasource.dart';
|
||||
|
||||
part 'api_interceptor.g.dart';
|
||||
|
||||
@@ -35,15 +34,16 @@ class AuthStorageKeys {
|
||||
// Auth Interceptor
|
||||
// ============================================================================
|
||||
|
||||
/// Interceptor for adding ERPNext session tokens to requests
|
||||
/// Interceptor for adding Frappe/ERPNext session tokens to requests
|
||||
///
|
||||
/// Adds SID (Session ID) and CSRF token from Hive storage to request headers.
|
||||
/// Adds Cookie (with SID) and X-Frappe-CSRF-Token from FlutterSecureStorage.
|
||||
/// Uses the centralized FrappeAuthService for session management.
|
||||
class AuthInterceptor extends Interceptor {
|
||||
AuthInterceptor(this._prefs, this._dio, this._authLocalDataSource);
|
||||
AuthInterceptor(this._prefs, this._dio, this._secureStorage);
|
||||
|
||||
final SharedPreferences _prefs;
|
||||
final Dio _dio;
|
||||
final AuthLocalDataSource _authLocalDataSource;
|
||||
final FlutterSecureStorage _secureStorage;
|
||||
|
||||
@override
|
||||
void onRequest(
|
||||
@@ -52,13 +52,24 @@ class AuthInterceptor extends Interceptor {
|
||||
) async {
|
||||
// Check if this endpoint requires authentication
|
||||
if (_requiresAuth(options.path)) {
|
||||
// Get session data from secure storage (async)
|
||||
final sid = await _authLocalDataSource.getSid();
|
||||
final csrfToken = await _authLocalDataSource.getCsrfToken();
|
||||
// Get session data from secure storage
|
||||
final sid = await _secureStorage.read(key: 'frappe_sid');
|
||||
final csrfToken = await _secureStorage.read(key: 'frappe_csrf_token');
|
||||
final fullName = await _secureStorage.read(key: 'frappe_full_name');
|
||||
final userId = await _secureStorage.read(key: 'frappe_user_id');
|
||||
|
||||
if (sid != null && csrfToken != null) {
|
||||
// Add ERPNext session headers
|
||||
options.headers['Cookie'] = 'sid=$sid';
|
||||
// Build cookie header with all required fields
|
||||
final cookieHeader = [
|
||||
'sid=$sid',
|
||||
'full_name=${fullName ?? "User"}',
|
||||
'system_user=no',
|
||||
'user_id=${userId != null ? Uri.encodeComponent(userId) : ApiConstants.frappePublicUserId}',
|
||||
'user_image=',
|
||||
].join('; ');
|
||||
|
||||
// Add Frappe session headers
|
||||
options.headers['Cookie'] = cookieHeader;
|
||||
options.headers['X-Frappe-CSRF-Token'] = csrfToken;
|
||||
}
|
||||
|
||||
@@ -276,9 +287,20 @@ class LoggingInterceptor extends Interceptor {
|
||||
name: 'HTTP Response',
|
||||
);
|
||||
developer.log(
|
||||
'║ Data: ${_truncateData(response.data, 500)}',
|
||||
'║ Headers: ${response.headers.map}',
|
||||
name: 'HTTP Response',
|
||||
);
|
||||
|
||||
// Log full response data (not truncated for debugging)
|
||||
final responseData = response.data;
|
||||
if (responseData != null) {
|
||||
if (responseData is String) {
|
||||
developer.log('║ Response: $responseData', name: 'HTTP Response');
|
||||
} else {
|
||||
developer.log('║ Response: ${_truncateData(responseData, 2000)}', name: 'HTTP Response');
|
||||
}
|
||||
}
|
||||
|
||||
developer.log(
|
||||
'╚══════════════════════════════════════════════════════════════',
|
||||
name: 'HTTP Response',
|
||||
@@ -534,14 +556,13 @@ Future<SharedPreferences> sharedPreferences(Ref ref) async {
|
||||
Future<AuthInterceptor> authInterceptor(Ref ref, Dio dio) async {
|
||||
final prefs = await ref.watch(sharedPreferencesProvider.future);
|
||||
|
||||
// Create AuthLocalDataSource with FlutterSecureStorage
|
||||
// Use FlutterSecureStorage for Frappe session
|
||||
const secureStorage = FlutterSecureStorage(
|
||||
aOptions: AndroidOptions(encryptedSharedPreferences: true),
|
||||
iOptions: IOSOptions(accessibility: KeychainAccessibility.first_unlock),
|
||||
);
|
||||
final authLocalDataSource = AuthLocalDataSource(secureStorage);
|
||||
|
||||
return AuthInterceptor(prefs, dio, authLocalDataSource);
|
||||
return AuthInterceptor(prefs, dio, secureStorage);
|
||||
}
|
||||
|
||||
/// Provider for LoggingInterceptor
|
||||
|
||||
@@ -114,7 +114,7 @@ final class AuthInterceptorProvider
|
||||
}
|
||||
}
|
||||
|
||||
String _$authInterceptorHash() => r'3f964536e03e204d09cc9120dd9d961b6d6d4b71';
|
||||
String _$authInterceptorHash() => r'1221aab024b7c4d9fd393f7681f3ba094286a375';
|
||||
|
||||
/// Provider for AuthInterceptor
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
/// - Retry logic
|
||||
library;
|
||||
|
||||
import 'package:curl_logger_dio_interceptor/curl_logger_dio_interceptor.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:dio_cache_interceptor/dio_cache_interceptor.dart';
|
||||
import 'package:dio_cache_interceptor_hive_store/dio_cache_interceptor_hive_store.dart';
|
||||
@@ -382,19 +383,21 @@ Future<Dio> dio(Ref ref) async {
|
||||
},
|
||||
)
|
||||
// Add interceptors in order
|
||||
// 1. Logging interceptor (first to log everything)
|
||||
// 1. Curl interceptor (first to log cURL commands)
|
||||
..interceptors.add(CurlLoggerDioInterceptor())
|
||||
// 2. Logging interceptor
|
||||
..interceptors.add(ref.watch(loggingInterceptorProvider))
|
||||
// 2. Auth interceptor (add tokens to requests)
|
||||
// 3. Auth interceptor (add tokens to requests)
|
||||
..interceptors.add(await ref.watch(authInterceptorProvider(dio).future))
|
||||
// 3. Cache interceptor
|
||||
// 4. Cache interceptor
|
||||
..interceptors.add(
|
||||
DioCacheInterceptor(
|
||||
options: await ref.watch(cacheOptionsProvider.future),
|
||||
),
|
||||
)
|
||||
// 4. Retry interceptor
|
||||
// 5. Retry interceptor
|
||||
..interceptors.add(RetryInterceptor(ref.watch(networkInfoProvider)))
|
||||
// 5. Error transformer (last to transform all errors)
|
||||
// 6. Error transformer (last to transform all errors)
|
||||
..interceptors.add(ref.watch(errorTransformerInterceptorProvider));
|
||||
|
||||
return dio;
|
||||
|
||||
@@ -131,7 +131,7 @@ final class DioProvider
|
||||
}
|
||||
}
|
||||
|
||||
String _$dioHash() => r'f15495e99d11744c245e2be892657748aeeb8ae7';
|
||||
String _$dioHash() => r'40bb4b1008c8259c9db4b19bcee674aa6732810c';
|
||||
|
||||
/// Provider for DioClient
|
||||
|
||||
|
||||
Reference in New Issue
Block a user