From c3137480f786427d81942cbb99982c358e982c14 Mon Sep 17 00:00:00 2001 From: XavierChanth Date: Mon, 9 Dec 2024 14:51:53 -0500 Subject: [PATCH] fix: activation from non-teapot status --- .../widgets/activate_atsign_dialog.dart | 45 +++++++++++++++++ .../onboarding/widgets/onboarding_button.dart | 49 +++++++------------ packages/dart/npt_flutter/pubspec.yaml | 4 +- 3 files changed, 64 insertions(+), 34 deletions(-) diff --git a/packages/dart/npt_flutter/lib/features/onboarding/widgets/activate_atsign_dialog.dart b/packages/dart/npt_flutter/lib/features/onboarding/widgets/activate_atsign_dialog.dart index bfb3d582e..eb6b1b1da 100644 --- a/packages/dart/npt_flutter/lib/features/onboarding/widgets/activate_atsign_dialog.dart +++ b/packages/dart/npt_flutter/lib/features/onboarding/widgets/activate_atsign_dialog.dart @@ -1,10 +1,12 @@ import 'dart:convert'; import 'package:at_onboarding_flutter/at_onboarding_flutter.dart'; +import 'package:at_server_status/at_server_status.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:npt_flutter/app.dart'; import 'package:npt_flutter/features/onboarding/util/activate_util.dart'; +import 'package:npt_flutter/features/onboarding/util/onboarding_util.dart'; import 'package:npt_flutter/widgets/spinner.dart'; import 'package:pin_code_fields/pin_code_fields.dart'; @@ -14,12 +16,16 @@ class ActivateAtsignDialog extends StatefulWidget { final String apiKey; final String atSign; final AtOnboardingConfig config; + final bool waitForTeapot; + final NoPortsOnboardingUtil onboardingUtil; const ActivateAtsignDialog({ super.key, required this.atSign, required this.apiKey, required this.config, required this.registrarUrl, + required this.waitForTeapot, + required this.onboardingUtil, }); @override @@ -170,6 +176,10 @@ class _ActivateAtsignDialogState extends State { status = ActivationStatus.activating; }); + // This does two things: + // 1. If the atSign is not in teapot, it will (assuming success) + // start activating the atSign as if you hit "Activate" in the dashboard + // 2. It will trigger the email/text OTP var (:cramkey, :errorMessage) = await util.verifyActivation( atsign: widget.atSign, otp: pinController.text, @@ -191,6 +201,41 @@ class _ActivateAtsignDialogState extends State { return; } + // If the atSign wasn't in teapot when we arrived at this screen, + // we should wait until the atSign is in teapot + if (widget.waitForTeapot) { + int round = 1; + getStatus() async { + return (await widget.onboardingUtil.atServerStatus(widget.atSign)).status(); + } + + AtSignStatus? atSignStatus = await getStatus(); + while (atSignStatus != AtSignStatus.teapot) { + // 6 * 5 = 30 seconds + // 12 * 5 = 60 seconds + if (round > 12) { + break; + } + await Future.delayed(const Duration(seconds: 5)); + round++; + atSignStatus = (await getStatus()); + } + + // If the Atsign is still not in teapot after the waiting period + // Then return an error + if (atSignStatus != AtSignStatus.teapot) { + if (mounted) { + Navigator.of(context).pop( + AtOnboardingResult.error(message: strings.errorAuthenticationTimedOut), + ); + } + return; + } + } + + // Assuming we got the correct OTP, and we are in teapot, + // being activation: Generating keys, bootstrapping server, etc. + // i.e. all the stuff to go from teapot -> activated var result = await util.onboardFromCramKey( atsign: widget.atSign, cramkey: cramkey, diff --git a/packages/dart/npt_flutter/lib/features/onboarding/widgets/onboarding_button.dart b/packages/dart/npt_flutter/lib/features/onboarding/widgets/onboarding_button.dart index 87c48b0e0..2fb5883b9 100644 --- a/packages/dart/npt_flutter/lib/features/onboarding/widgets/onboarding_button.dart +++ b/packages/dart/npt_flutter/lib/features/onboarding/widgets/onboarding_button.dart @@ -64,9 +64,7 @@ class _OnboardingButtonState extends State { bool shouldOnboard = await selectAtsign(); if (shouldOnboard && context.mounted) { var atsignInformation = context.read().state; - onboard( - atsign: atsignInformation.atSign, - rootDomain: atsignInformation.rootDomain); + onboard(atsign: atsignInformation.atSign, rootDomain: atsignInformation.rootDomain); } }, icon: PhosphorIcon(PhosphorIcons.arrowUpRight()), @@ -75,10 +73,8 @@ class _OnboardingButtonState extends State { ), iconAlignment: IconAlignment.end, ), - _OnboardingButtonStatus.picking => - Text(strings.onboardingButtonStatusPicking), - _OnboardingButtonStatus.processingFile => - Text(strings.onboardingButtonStatusProcessingFile), + _OnboardingButtonStatus.picking => Text(strings.onboardingButtonStatusPicking), + _OnboardingButtonStatus.processingFile => Text(strings.onboardingButtonStatusProcessingFile), }; } @@ -109,12 +105,8 @@ class _OnboardingButtonState extends State { return results ?? false; } - Future onboard( - {required String atsign, - required String rootDomain, - bool isFromInitState = false}) async { - var atSigns = - await KeyChainManager.getInstance().getAtSignListFromKeychain(); + Future onboard({required String atsign, required String rootDomain, bool isFromInitState = false}) async { + var atSigns = await KeyChainManager.getInstance().getAtSignListFromKeychain(); var apiKey = await Constants.appAPIKey; var config = AtOnboardingConfig( atClientPreference: await loadAtClientPreference(rootDomain), @@ -163,8 +155,7 @@ class _OnboardingButtonState extends State { SnackBar( backgroundColor: Colors.red, content: Text( - onboardingResult?.message ?? - AppLocalizations.of(context)!.onboardingError, + onboardingResult?.message ?? AppLocalizations.of(context)!.onboardingError, ), ), ); @@ -174,8 +165,7 @@ class _OnboardingButtonState extends State { } } - Future handleAtsignByStatus( - String atsign, NoPortsOnboardingUtil util) async { + Future handleAtsignByStatus(String atsign, NoPortsOnboardingUtil util) async { AtStatus status; try { @@ -187,8 +177,8 @@ class _OnboardingButtonState extends State { } AtOnboardingResult? result; if (!mounted) return null; - - switch (status.status()) { + var initialStatus = status.status(); + switch (initialStatus) { // Automatically start activation with the already entered atSign case AtSignStatus.unavailable: case AtSignStatus.teapot: @@ -201,12 +191,9 @@ class _OnboardingButtonState extends State { break; } AtOnboardingConstants.setApiKey(apiKey); - AtOnboardingConstants.rootDomain = - util.config.atClientPreference.rootDomain; + AtOnboardingConstants.rootDomain = util.config.atClientPreference.rootDomain; - await AtOnboardingLocalizations.load( - LanguageUtil.getLanguageFromLocale(Locale(Platform.localeName)) - .locale); + await AtOnboardingLocalizations.load(LanguageUtil.getLanguageFromLocale(Locale(Platform.localeName)).locale); if (!mounted) return null; Map apis = { "root.atsign.org": "my.atsign.com", @@ -227,19 +214,18 @@ class _OnboardingButtonState extends State { apiKey: apiKey, config: util.config, registrarUrl: regUrl, + onboardingUtil: util, + waitForTeapot: initialStatus != AtSignStatus.teapot, ), ); if (result is AtOnboardingResult) { //Update primary atsign after onboard success - if (result.status == AtOnboardingResultStatus.success && - result.atsign != null) { + if (result.status == AtOnboardingResultStatus.success && result.atsign != null) { var onboardingService = OnboardingService.getInstance(); - bool res = await onboardingService.changePrimaryAtsign( - atsign: result.atsign!); + bool res = await onboardingService.changePrimaryAtsign(atsign: result.atsign!); if (!res) { - result = AtOnboardingResult.error( - message: strings.errorSwitchAtSignFailed); + result = AtOnboardingResult.error(message: strings.errorSwitchAtSignFailed); } } } @@ -262,8 +248,7 @@ class _OnboardingButtonState extends State { return result; } - Future handleFileUploadStatusStream( - Stream statusStream, String atsign) async { + Future handleFileUploadStatusStream(Stream statusStream, String atsign) async { AtOnboardingResult? result; outer: await for (FileUploadStatus status in statusStream) { diff --git a/packages/dart/npt_flutter/pubspec.yaml b/packages/dart/npt_flutter/pubspec.yaml index 1d206619a..44cea6d27 100644 --- a/packages/dart/npt_flutter/pubspec.yaml +++ b/packages/dart/npt_flutter/pubspec.yaml @@ -16,13 +16,13 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 1.1.4+4 +version: 1.1.5+5 msix_config: display_name: "NoPorts Desktop" publisher_display_name: Atsign Inc identity_name: TheCompany.NoPortsDesktop publisher: CN=BBFE1D0B-F713-4C7F-B375-5EA851CBB1FF - msix_version: 1.1.4.4 + msix_version: 1.1.5.0 logo_path: "assets/logo.png" capabilities: internetClient store: true