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 : }
|