LCOV - code coverage report
Current view: top level - lib/api/utils - api_reactions.dart Coverage Total Hit
Test: lcov.info Lines: 82.9 % 35 29
Test Date: 2025-05-10 20:26:13 Functions: - 0 0

            Line data    Source code
       1              : import 'package:amadeus_proto/api/routes/auth.dart';
       2              : import 'package:amadeus_proto/api/routes/profile.dart';
       3              : import 'package:amadeus_proto/api/utils/api_base.dart';
       4              : import 'package:amadeus_proto/api/utils/api_error.dart';
       5              : import 'package:amadeus_proto/app_state.dart';
       6              : import 'package:amadeus_proto/pages/login/widgets/login_frame.dart';
       7              : import 'package:either_dart/either.dart';
       8              : import 'package:flutter/material.dart';
       9              : import 'package:flutter_secure_storage/flutter_secure_storage.dart';
      10              : import 'package:provider/provider.dart';
      11              : 
      12              : const String invalidOrExpiredToken = "AMB0010";
      13              : const String userRefreshInvalidTokenUserUUID = "AMB1016";
      14              : const String userRefreshInvalidTokenUID = "AMB1017";
      15              : const String userRefreshUserNotFound = "AMB1018";
      16              : 
      17              : /// Handler for calling API error reactions
      18              : class ApiReactions {
      19              :   /// Contructor for the ApiReactions class
      20              :   ///
      21              :   /// Takes a [FlutterSecureStorage] instance has parameter, if none is provided, a new one will be created
      22            6 :   ApiReactions({FlutterSecureStorage? storage})
      23              :       : _storage = storage ?? const FlutterSecureStorage();
      24              : 
      25              :   final FlutterSecureStorage _storage;
      26              : 
      27              :   /// Call a reaction depending on the [errorCode] with the provided [context]
      28              :   /// If the error code is not associated with a reaction, the function does nothing
      29            6 :   void executeReaction(BuildContext context, String errorCode,
      30              :       [String? route]) {
      31            6 :     final ApiBase apiBase = ApiBase.read(context);
      32              :     switch ((errorCode, route)) {
      33              :       // Invalid token
      34            7 :       case (invalidOrExpiredToken, "/auth/refresh"):
      35            0 :         if (apiBase.refreshToken == null) {
      36            0 :           executeReaction(context, invalidOrExpiredToken, "");
      37              :           return;
      38              :         }
      39              :         apiBase
      40            0 :             .refreshAuthToken()
      41            0 :             .mapRight((_) => apiBase.getMyProfile().mapRight((user) {
      42            0 :                   if (context.mounted) {
      43            0 :                     context.read<AppState>().userId = user.id;
      44              :                   }
      45              :                 }));
      46              :       // Back-end errors
      47              :       // Login category (10)
      48              :       // Invalid refresh token
      49              :       case (invalidOrExpiredToken, _):
      50            6 :       case (userRefreshInvalidTokenUserUUID, _):
      51            6 :       case (userRefreshInvalidTokenUID, _):
      52            6 :       case (userRefreshUserNotFound, _):
      53            1 :         Future.wait(
      54            5 :                 [_storage.read(key: "email"), _storage.read(key: "password")])
      55            2 :             .then((value) {
      56            2 :           if (value[0] != null && value[1] != null) {
      57              :             apiBase
      58            3 :                 .login(value[0]!, value[1]!)
      59            2 :                 .then((result) {
      60            1 :                   if (result.isLeft) {
      61            2 :                     _invalidLoginRedirect(context, _storage);
      62              :                   }
      63              :                   return result;
      64              :                 })
      65            5 :                 .mapRight((_) => apiBase.getMyProfile().mapRight((user) {
      66            1 :                       if (context.mounted) {
      67            3 :                         context.read<AppState>().userId = user.id;
      68              :                       }
      69              :                     }))
      70            2 :                 .onError((error, _) {
      71            2 :                   _invalidLoginRedirect(context, _storage);
      72            2 :                   return Left(ApiError(
      73              :                       httpErrorCode: 400,
      74              :                       apiStatusCode: "AMBXXXX",
      75            1 :                       message: error.toString())); // Ensure a return value
      76              :                 });
      77              :             return;
      78              :           }
      79            1 :           Navigator.push(
      80            2 :               context, MaterialPageRoute(builder: (_) => const LoginFrame()));
      81              :         });
      82              :       default:
      83              :         return;
      84              :     }
      85              :   }
      86              : }
      87              : 
      88            1 : void _invalidLoginRedirect(BuildContext context, FlutterSecureStorage storage) {
      89            1 :   storage.delete(key: "email");
      90            1 :   storage.delete(key: "password");
      91            1 :   Navigator.push(
      92            2 :       context, MaterialPageRoute(builder: (_) => const LoginFrame()));
      93              : }
        

Generated by: LCOV version 2.3-1