Ferry-200 před 8 měsíci
rodič
revize
5a3fc8753e

+ 11 - 5
summer-ospp/2024/Flutter/maxkey_flutter/lib/maxkey/maxkey.dart

@@ -37,14 +37,15 @@ class MaxKey with ChangeNotifier {
         handler.next(response);
       },
       onError: (error, handler) {
+        LOGGER.e("InterceptorsWrapper.onError(): ");
         LOGGER.e(error.type);
         LOGGER.e(error.response);
         if (error.type == DioExceptionType.badResponse) {
           SCAFFOLD_MESSENGER_KEY.currentState?.showSnackBar(
             SnackBar(
-              content: const Text("Please login again."),
+              content: const Text("登陆状态过期。请重新登陆"),
               action: SnackBarAction(
-                label: "Login",
+                label: "重新登陆",
                 onPressed: () async {
                   _dio.options.headers.remove(HttpHeaders.authorizationHeader);
                   await MaxKeyPersistent.instance.clearToken();
@@ -62,6 +63,7 @@ class MaxKey with ChangeNotifier {
   }
 
   void updateBaseUrl() {
+    LOGGER.i("MaxKey.updateBaseUrl(): ");
     LOGGER.i("old baseUrl: ${_dio.options.baseUrl}");
     _dio.options.baseUrl = MaxKeyPersistent.instance.baseUrl;
     LOGGER.i("new baseUrl: ${_dio.options.baseUrl}");
@@ -72,16 +74,20 @@ class MaxKey with ChangeNotifier {
 
   Future<bool> maxKeyNetworkTest({String? host}) async {
     try {
+      LOGGER.i("MaxKey.maxKeyNetworkTest(): ");
       LOGGER.i(
         "[MaxKeyNetworkTest] GET: ${host == null ? MaxKeyPersistent.instance.baseUrl : "http://$host/sign"}",
       );
 
-      await _dio.get(
-        host == null ? MaxKeyPersistent.instance.baseUrl : "http://$host/sign",
-      );
+      await _dio
+          .get(host == null
+              ? MaxKeyPersistent.instance.baseUrl
+              : "http://$host/sign")
+          .timeout(const Duration(seconds: 5));
       LOGGER.i("MaxKeyNetworkTest: true");
       return true;
     } catch (err) {
+      LOGGER.e("MaxKey.maxKeyNetworkTest(): ");
       LOGGER.e(err);
     }
     LOGGER.i("MaxKeyNetworkTest: false");

+ 12 - 1
summer-ospp/2024/Flutter/maxkey_flutter/lib/maxkey/services/authn.service.dart

@@ -14,6 +14,7 @@ class AuthnService {
   /// 获取 state 类型
   Future<String?> get() async {
     try {
+      LOGGER.i("AuthnService.get(): ");
       LOGGER.i("GET: /login/get?_allow_anonymous=true");
 
       final res = await _dio.get(
@@ -22,6 +23,7 @@ class AuthnService {
       );
       return res.data["data"]["state"];
     } catch (err) {
+      LOGGER.e("AuthnService.get(): ");
       LOGGER.e(err);
     }
     return null;
@@ -33,6 +35,7 @@ class AuthnService {
     required String mobile,
   }) async {
     try {
+      LOGGER.i("AuthnService.produceOtp(): ");
       LOGGER.i("GET: /login/sendotp/$mobile?_allow_anonymous=true");
 
       final res = await _dio.get(
@@ -49,6 +52,7 @@ class AuthnService {
 
       return true;
     } catch (err) {
+      LOGGER.e("AuthnService.produceOtp(): ");
       LOGGER.e(err);
     }
     return false;
@@ -63,6 +67,7 @@ class AuthnService {
     required String captcha,
   }) async {
     try {
+      LOGGER.i("AuthnService.loginNormal(): ");
       LOGGER.i("POST: /login/signin?_allow_anonymous=true");
 
       final res = await _dio.post(
@@ -91,6 +96,7 @@ class AuthnService {
       );
       return true;
     } catch (err) {
+      LOGGER.e("AuthnService.loginNormal(): ");
       LOGGER.e(err);
     }
     return false;
@@ -100,8 +106,10 @@ class AuthnService {
     required ExpectedErrorHandler expectedErrorHandler,
     required String code,
   }) async {
+    LOGGER.i("AuthnService.scanCode(): ");
     final token = MaxKeyPersistent.instance.token;
     if (token == null) {
+      LOGGER.i("未登录");
       expectedErrorHandler("未登录");
       return false;
     }
@@ -122,6 +130,7 @@ class AuthnService {
 
       return true;
     } catch (err) {
+      LOGGER.e("AuthnService.scanCode(): ");
       LOGGER.e(err);
     }
     return false;
@@ -148,9 +157,11 @@ class AuthnService {
   /// 登出并清除本地缓存的 token
   Future<void> logout() async {
     try {
+      LOGGER.i("AuthnService.logout(): ");
       LOGGER.i("GET: /logout");
-      await _dio.get("/logout");
+      await _dio.get("/logout").timeout(const Duration(seconds: 5));
     } catch (err) {
+      LOGGER.e("AuthnService.logout(): ");
       LOGGER.e(err);
     }
 

+ 2 - 0
summer-ospp/2024/Flutter/maxkey_flutter/lib/maxkey/services/image_captcha.service.dart

@@ -10,6 +10,7 @@ class ImageCaptchaService {
 
   Future<Uint8List?> captcha({required String state}) async {
     try {
+      LOGGER.i("ImageCaptchaService.captcha(): ");
       LOGGER.i("GET: /captcha?_allow_anonymous=true");
 
       final res = await _dio.get(
@@ -20,6 +21,7 @@ class ImageCaptchaService {
       final String base64Image = res.data["data"]["image"];
       return base64.decode(base64Image.split(",")[1]);
     } catch (err) {
+      LOGGER.e("ImageCaptchaService.captcha(): ");
       LOGGER.e(err);
     }
     return null;

+ 2 - 0
summer-ospp/2024/Flutter/maxkey_flutter/lib/maxkey/services/time_based.service.dart

@@ -7,6 +7,7 @@ class TimeBasedService {
 
   Future<bool> verify({required String totpCode}) async {
     try {
+      LOGGER.i("TimeBasedService.verify(): ");
       LOGGER.i("GET: /config/verify?otp=$totpCode");
 
       final res = await _dio.get(
@@ -22,6 +23,7 @@ class TimeBasedService {
       LOGGER.i("验证成功");
       return true;
     } catch (err) {
+      LOGGER.e("TimeBasedService.verify(): ");
       LOGGER.e(err);
     }
     return false;

+ 4 - 0
summer-ospp/2024/Flutter/maxkey_flutter/lib/maxkey/services/users.service.dart

@@ -212,6 +212,7 @@ class UsersService {
 
   Future<MaxKeyUser?> getBasicUserInfo() async {
     try {
+      LOGGER.i("UsersService.getBasicUserInfo(): ");
       LOGGER.i("GET: /users/profile/get");
 
       final res = await _dio.get("/users/profile/get");
@@ -221,6 +222,7 @@ class UsersService {
       }
       return MaxKeyUser.fromMap(res.data);
     } catch (err) {
+      LOGGER.i("UsersService.getBasicUserInfo(): ");
       LOGGER.e(err);
     }
     return null;
@@ -228,6 +230,7 @@ class UsersService {
 
   Future<MaxKeyUserInfo?> getFullUserInfo() async {
     try {
+      LOGGER.i("UsersService.getFullUserInfo(): ");
       LOGGER.i("GET: /users/profile/get");
 
       final res = await _dio.get("/users/profile/get");
@@ -238,6 +241,7 @@ class UsersService {
 
       return MaxKeyUserInfo.fromMap(res.data["data"]);
     } catch (err) {
+      LOGGER.e("UsersService.getFullUserInfo(): ");
       LOGGER.e(err);
     }
     return null;

+ 7 - 1
summer-ospp/2024/Flutter/maxkey_flutter/lib/pages/home_page/components/new_totp_btn.dart

@@ -17,15 +17,20 @@ class _NewTotpBtn extends StatelessWidget {
       child: InkWell(
         borderRadius: BorderRadius.circular(8.0),
         onTap: () async {
+          LOGGER.i("_NewTotpBtn: ");
           final qrCodeValue = await context.push<String?>(
             RoutePath.scanPage,
             extra: AppLocalizations.of(context)!.homePageNewTotpBtnScanPage,
           );
 
-          if (qrCodeValue == null) return;
+          if (qrCodeValue == null) {
+            LOGGER.w("No QR code.");
+            return;
+          }
 
           final newTotp = Totp.fromUri(qrCodeValue);
           if (newTotp == null) {
+            LOGGER.w("Unsupported QR code.");
             if (context.mounted) {
               ScaffoldMessenger.of(context).showSnackBar(
                 SnackBar(content: Text(AppLocalizations.of(context)!.homePagenewTotpBtnErr)),
@@ -39,6 +44,7 @@ class _NewTotpBtn extends StatelessWidget {
           await MaxKeyPersistent.instance.saveTotps(totps);
 
           controller.update();
+          LOGGER.i("TOTP added.");
         },
         child: Padding(
           padding: const EdgeInsets.symmetric(vertical: 16.0),

+ 12 - 8
summer-ospp/2024/Flutter/maxkey_flutter/lib/pages/home_page/components/totp_list_view.dart

@@ -73,7 +73,9 @@ class _TotpListView extends StatelessWidget {
             listenable: controller,
             builder: (context, _) {
               if (controller.totps.isEmpty) {
-                return Center(child: Text(AppLocalizations.of(context)!.homePageTotpListViewNoTOTP));
+                return Center(
+                    child: Text(AppLocalizations.of(context)!
+                        .homePageTotpListViewNoTOTP));
               }
 
               return Column(
@@ -120,19 +122,22 @@ class _TotpListView extends StatelessWidget {
                           final confirm = await showDialog<bool>(
                             context: context,
                             builder: (context) => AlertDialog(
-                              title: Text(AppLocalizations.of(context)!.homePageTotpListViewConfirmDialog),
+                              title: Text(AppLocalizations.of(context)!
+                                  .homePageTotpListViewConfirmDialog),
                               actions: [
                                 TextButton(
                                   onPressed: () {
                                     Navigator.of(context).pop(false);
                                   },
-                                  child: Text(AppLocalizations.of(context)!.homePageTotpListViewConfirmDialogCancelBtn),
+                                  child: Text(AppLocalizations.of(context)!
+                                      .homePageTotpListViewConfirmDialogCancelBtn),
                                 ),
                                 TextButton(
                                   onPressed: () {
                                     Navigator.of(context).pop(true);
                                   },
-                                  child: Text(AppLocalizations.of(context)!.homePageTotpListViewConfirmDialogConfirmBtn),
+                                  child: Text(AppLocalizations.of(context)!
+                                      .homePageTotpListViewConfirmDialogConfirmBtn),
                                 ),
                               ],
                             ),
@@ -179,7 +184,8 @@ class _TotpCodeCardState extends State<_TotpCodeCard> {
 
   int getValidity() {
     final utc = DateTime.timestamp();
-    return widget.totp.interval - (utc.millisecondsSinceEpoch ~/ 1000 % 30);
+    return widget.totp.interval -
+        (utc.millisecondsSinceEpoch ~/ 1000 % widget.totp.interval);
   }
 
   @override
@@ -189,12 +195,10 @@ class _TotpCodeCardState extends State<_TotpCodeCard> {
     validity = getValidity();
 
     updater = Timer.periodic(const Duration(seconds: 1), (timer) {
-      validity = getValidity();
-
       setState(() {
         validity = getValidity();
         if (validity == widget.totp.interval) {
-          LOGGER.i(DateTime.now());
+          LOGGER.i("totp: ${DateTime.now()}");
           password = widget.totp.now;
         }
       });