diff --git a/lib/core/network/AppInterceptors.dart b/lib/core/network/AppInterceptors.dart deleted file mode 100644 index 019f6c0..0000000 --- a/lib/core/network/AppInterceptors.dart +++ /dev/null @@ -1,28 +0,0 @@ -import 'package:aranduapp/core/data/local/StorageValue.dart'; -import 'package:aranduapp/core/log/Log.dart'; -import 'package:dio/dio.dart'; - -class AppInterceptors extends Interceptor { - @override - Future onRequest( - RequestOptions options, - RequestInterceptorHandler handler - ) async { - super.onRequest(options, handler); - - try { - String? token = await StorageValue.getInstance().getAuthToken(); - - if (token != null) { - options.headers['Authorization'] = 'asdfasdfasdfasdfasdfasdfasdfsadfsadf'; - } else { - Log.e('Token não encontrado'); - } - } catch (e) { - Log.e('Erro ao recuperar token: $e'); - } - - handler.next(options); - } -} - diff --git a/lib/core/network/app_interceptors.dart b/lib/core/network/app_interceptors.dart new file mode 100644 index 0000000..651249d --- /dev/null +++ b/lib/core/network/app_interceptors.dart @@ -0,0 +1,53 @@ +import 'package:aranduapp/core/data/local/StorageValue.dart'; +import 'package:aranduapp/core/log/Log.dart'; +import 'package:aranduapp/core/network/token_manager/auth_service.dart'; +import 'package:aranduapp/core/network/token_manager/model/refresh_token_response.dart'; +import 'package:dio/dio.dart'; + +class AppInterceptors extends Interceptor { + @override + Future onRequest( + RequestOptions options, RequestInterceptorHandler handler) async { + String? token = await StorageValue.getInstance().getAuthToken(); + + Log.w(token); + + if (token != null) { + options.headers['Authorization'] = token; + } else { + Log.w('Token não encontrado'); + } + + super.onRequest(options, handler); + } + + @override + Future onError(DioException err, ErrorInterceptorHandler handler) async { + if (err.response?.statusCode == 401) { + try { + Log.i('Token expirado. Tentando atualizar o token...'); + + RefreshTokenResponse tokens = + await AuthService().refreshToken(); + + final requestOptions = err.requestOptions; + + requestOptions.headers['Authorization'] = 'Bearer ${tokens.authToken}'; + + final response = await Dio().request( + requestOptions.path, + options: Options( + method: requestOptions.method, + headers: requestOptions.headers, + ), + data: requestOptions.data, + ); + + Log.i('Token expirado atualizado.'); + return handler.resolve(response); + } catch (e) { + super.onError(err, handler); + } + } + } +} diff --git a/lib/core/network/BaseApi.dart b/lib/core/network/base_api.dart similarity index 52% rename from lib/core/network/BaseApi.dart rename to lib/core/network/base_api.dart index b5db224..2f3e284 100644 --- a/lib/core/network/BaseApi.dart +++ b/lib/core/network/base_api.dart @@ -1,18 +1,22 @@ -import 'package:aranduapp/core/data/local/StorageValue.dart'; import 'package:aranduapp/core/log/Log.dart'; -import 'package:aranduapp/core/network/AppInterceptors.dart'; +import 'package:aranduapp/core/network/app_interceptors.dart'; + import 'package:dio/dio.dart'; class BaseApi { final Dio _dio; - static BaseApi? _instance; + static BaseApi? _authInstance, _nonAuthInstance; + + final String url = 'https://arandu-user-service.onrender.com'; - BaseApi._internal() : _dio = Dio() { - _dio.options.baseUrl = 'http://192.168.1.107:3000'; + BaseApi._internal(bool auth) : _dio = Dio() { + _dio.options.baseUrl = url; _dio.options.connectTimeout = const Duration(seconds: 5); _dio.options.receiveTimeout = const Duration(seconds: 5); + if (auth) _dio.interceptors.add(AppInterceptors()); + _dio.interceptors.add(LogInterceptor( requestBody: true, responseBody: true, @@ -22,17 +26,17 @@ class BaseApi { request: true)); } - static BaseApi getInstance() { - return _instance ??= BaseApi._internal(); + static BaseApi getInstance({required bool auth}) { + if (auth) { + return _authInstance ??= BaseApi._internal(auth); + } else { + return _nonAuthInstance ??= BaseApi._internal(auth); + } } - Future get( {required String path, Map? queryParameters}) async { + Future get( + {required String path, Map? queryParameters}) async { try { - _dio.options.headers = { - 'Authorization': - 'Bearer ${await StorageValue.getInstance().getAuthToken()}', - }; - return await _dio.get(path, queryParameters: queryParameters); } catch (e) { Log.e(e); @@ -42,11 +46,6 @@ class BaseApi { Future post({required String path, Object? data}) async { try { - _dio.options.headers = { - 'Authorization': - 'Bearer ${await StorageValue.getInstance().getAuthToken()}', - }; - return await _dio.post(path, data: data); } catch (e) { Log.e(e); diff --git a/lib/core/network/token_manager/auth_service.dart b/lib/core/network/token_manager/auth_service.dart new file mode 100644 index 0000000..44b103f --- /dev/null +++ b/lib/core/network/token_manager/auth_service.dart @@ -0,0 +1,31 @@ +import 'package:aranduapp/core/data/local/StorageValue.dart'; +import 'package:aranduapp/core/log/Log.dart'; +import 'package:aranduapp/core/network/base_api.dart'; +import 'package:aranduapp/core/network/token_manager/model/refresh_token_response.dart'; +import 'package:dio/dio.dart'; + +class AuthService { + Future refreshToken() async { + String? refresh = await StorageValue.getInstance().getRefreshToken(); + + assert(refresh != null); + + Response response = await BaseApi.getInstance(auth: false).post( + path: '/auth/refresh', + data: {'refreshToken': refresh}); + + RefreshTokenResponse tokens = + RefreshTokenResponse.fromJsonString(response.toString()); + + await StorageValue.getInstance().setAuthToken(tokens.authToken!); + await StorageValue.getInstance().setRefreshToken(tokens.refreshToken!); + + Log.i("Tokens atualizados com sucesso."); + + return tokens; + } + + Future validateToken() async { + await BaseApi.getInstance(auth: true).get(path: '/auth/validate-token'); + } +} diff --git a/lib/core/network/token_manager/model/refresh_token_response.dart b/lib/core/network/token_manager/model/refresh_token_response.dart new file mode 100644 index 0000000..4691cfc --- /dev/null +++ b/lib/core/network/token_manager/model/refresh_token_response.dart @@ -0,0 +1,18 @@ +import 'dart:convert'; + +class RefreshTokenResponse { + + String? authToken; + String? refreshToken; + + RefreshTokenResponse(this.authToken, this.refreshToken); + + factory RefreshTokenResponse.fromJsonString(String jsonString) { + Map json = jsonDecode(jsonString); + return RefreshTokenResponse( + json['accessToken'] as String?, + json['refreshToken'] as String? + ); + } + +} diff --git a/lib/ui/login/model/LoginResponse.dart b/lib/ui/login/model/LoginResponse.dart index 1ffdc7b..18b17c2 100644 --- a/lib/ui/login/model/LoginResponse.dart +++ b/lib/ui/login/model/LoginResponse.dart @@ -2,8 +2,8 @@ import 'dart:convert'; class LoginResponse { - String? authToken; - String? refreshToken; + String authToken; + String refreshToken; LoginResponse(this.authToken, this.refreshToken); @@ -11,8 +11,8 @@ class LoginResponse { factory LoginResponse.fromJsonString(String jsonString) { Map json = jsonDecode(jsonString); return LoginResponse( - json['accessToken'] as String?, - json['refreshToken'] as String? + json['accessToken']! as String, + json['refreshToken']! as String ); } diff --git a/lib/ui/login/service/LoginService.dart b/lib/ui/login/service/LoginService.dart index 1f550e5..0d85360 100644 --- a/lib/ui/login/service/LoginService.dart +++ b/lib/ui/login/service/LoginService.dart @@ -1,6 +1,7 @@ import 'package:aranduapp/core/data/local/StorageValue.dart'; import 'package:aranduapp/core/log/Log.dart'; -import 'package:aranduapp/core/network/BaseApi.dart'; +import 'package:aranduapp/core/network/base_api.dart'; +import 'package:aranduapp/core/network/token_manager/auth_service.dart'; import 'package:aranduapp/ui/login/model/LoginRequest.dart'; import 'package:aranduapp/ui/login/model/LoginResponse.dart'; import 'package:dio/dio.dart'; @@ -9,7 +10,7 @@ class LoginService { static Future login(LoginRequest loginRequest) async { Log.d('${loginRequest.email} ${loginRequest.password}'); - Response response = await BaseApi.getInstance().post( + Response response = await BaseApi.getInstance(auth: false).post( path: '/auth/login', data: { 'email': loginRequest.email, @@ -19,30 +20,14 @@ class LoginService { LoginResponse loginResponse = LoginResponse.fromJsonString(response.toString()); - assert( - loginResponse.authToken != null && loginResponse.refreshToken != null); - - await StorageValue.getInstance() - .setAuthToken(loginResponse.authToken ?? ''); + await StorageValue.getInstance().setAuthToken(loginResponse.authToken); await StorageValue.getInstance() - .setRefreshToken(loginResponse.refreshToken ?? ''); + .setRefreshToken(loginResponse.refreshToken); return response; } - static Future refreshToken() async { - Log.d('init reresh token'); - - await BaseApi.getInstance().get(path: '/auth/validate-token'); - - String? refresh = await StorageValue.getInstance().getRefreshToken(); - - assert(refresh != null); - - await BaseApi.getInstance().post( - path: '/auth/refresh', - data: {'refreshToken': refresh}); - - Log.d('finish reresh token'); + static Future validateToken() async { + await AuthService().refreshToken(); } } diff --git a/lib/ui/login/view/LoginView.dart b/lib/ui/login/view/LoginView.dart index 1eb7b2d..af81a82 100644 --- a/lib/ui/login/view/LoginView.dart +++ b/lib/ui/login/view/LoginView.dart @@ -44,7 +44,7 @@ class _LoginState extends State<_Login> { void initState() { super.initState(); _future = Provider.of(context, listen: false) - .getRefreshTokenFuture(); + .validateToken(); } @override diff --git a/lib/ui/login/viewModel/LoginViewModel.dart b/lib/ui/login/viewModel/LoginViewModel.dart index 5d241f2..a182eb1 100644 --- a/lib/ui/login/viewModel/LoginViewModel.dart +++ b/lib/ui/login/viewModel/LoginViewModel.dart @@ -5,8 +5,6 @@ import 'package:local_auth/local_auth.dart'; import 'package:aranduapp/ui/login/service/LoginService.dart'; import 'package:aranduapp/ui/login/model/LoginRequest.dart'; -import 'package:aranduapp/ui/home/view/HomeView.dart'; - class LoginViewModel extends ChangeNotifier { final BuildContext context; @@ -46,10 +44,8 @@ class LoginViewModel extends ChangeNotifier { } } - Future getRefreshTokenFuture() async { - await Future.delayed(const Duration(seconds: 2)); - - //await LoginService.refreshToken(); + Future validateToken() async { + await LoginService.validateToken(); } Future loginWithDeviceAuth() async { diff --git a/lib/ui/recover_account/service/RecoverAccountService.dart b/lib/ui/recover_account/service/RecoverAccountService.dart index 3afc7a2..2ab2331 100644 --- a/lib/ui/recover_account/service/RecoverAccountService.dart +++ b/lib/ui/recover_account/service/RecoverAccountService.dart @@ -1,4 +1,4 @@ -import 'package:aranduapp/core/network/BaseApi.dart'; +import 'package:aranduapp/core/network/base_api.dart'; import 'package:aranduapp/ui/recover_account/model/RecoverAccountRequest.dart'; class RecoverAccountService { @@ -6,7 +6,7 @@ class RecoverAccountService { static Future forgetPassword(RecoverAccountRequest recoverAccountRequest) async { - await BaseApi.getInstance().post( + await BaseApi.getInstance(auth:false).post( path: '/auth/forgot-password', data: { 'email' : recoverAccountRequest.email, diff --git a/lib/ui/register_account/service/RegisterService.dart b/lib/ui/register_account/service/RegisterService.dart index 090f0d1..620eafa 100644 --- a/lib/ui/register_account/service/RegisterService.dart +++ b/lib/ui/register_account/service/RegisterService.dart @@ -1,20 +1,14 @@ -import 'package:aranduapp/core/network/BaseApi.dart'; -import 'package:dio/dio.dart'; +import 'package:aranduapp/core/network/base_api.dart'; import '../model/RegisterRequest.dart'; class RegisterService { - static Future register(RegisterRequest registerRequest) async { - - await BaseApi.getInstance() + await BaseApi.getInstance(auth: false) .post(path: '/users', data: { 'name': registerRequest.name, 'email': registerRequest.email, 'username': registerRequest.userName, 'password': registerRequest.password, }); - } - } -