diff --git a/client/assets/next/img/connected_instance.svg b/client/assets/next/img/connected_instance.svg
new file mode 100644
index 0000000..e37cb01
--- /dev/null
+++ b/client/assets/next/img/connected_instance.svg
@@ -0,0 +1,11 @@
+
diff --git a/client/assets/next/img/idle_instance.svg b/client/assets/next/img/idle_instance.svg
new file mode 100644
index 0000000..3813f19
--- /dev/null
+++ b/client/assets/next/img/idle_instance.svg
@@ -0,0 +1,5 @@
+
diff --git a/client/assets/next/rive/openid_mfa.riv b/client/assets/next/rive/open_id.riv
similarity index 100%
rename from client/assets/next/rive/openid_mfa.riv
rename to client/assets/next/rive/open_id.riv
diff --git a/client/lib/enterprise/config_update.dart b/client/lib/enterprise/config_update.dart
index 0186ae6..326b538 100644
--- a/client/lib/enterprise/config_update.dart
+++ b/client/lib/enterprise/config_update.dart
@@ -118,9 +118,7 @@ class ConfigurationUpdater extends HookConsumerWidget {
instance.name,
updateResult,
);
- toaster.show(
- message: "Instance ${instance.name} updated: $message",
- );
+ talker.info("Instance ${instance.logName} updated: $message");
}
}
} catch (e) {
diff --git a/client/lib/enterprise/screens/mfa/openid_mfa_waiting_screen.dart b/client/lib/enterprise/screens/mfa/openid_mfa_waiting_screen.dart
index 3a8fe63..e34881b 100644
--- a/client/lib/enterprise/screens/mfa/openid_mfa_waiting_screen.dart
+++ b/client/lib/enterprise/screens/mfa/openid_mfa_waiting_screen.dart
@@ -9,6 +9,7 @@ import 'package:mobile/open/widgets/dg_app_bar.dart';
import 'package:mobile/open/widgets/dg_mfa_step_label.dart';
import 'package:mobile/open/widgets/dg_button.dart';
import 'package:mobile/open/widgets/dg_icon_button.dart';
+import 'package:mobile/open/widgets/rive_asset_animation.dart';
import 'package:mobile/open/widgets/toaster/toast_manager.dart';
import 'package:mobile/theme/color.dart';
import 'package:mobile/theme/text.dart';
@@ -117,9 +118,13 @@ class OpenIdMfaWaitingScreen extends HookConsumerWidget {
const SizedBox(height: 8),
Text(
"Waiting for authentication in your browser...",
- style: DgText.bodyXs400.copyWith(color: DgColor.fgWhite60),
+ style: DgText.bodySm400.copyWith(color: DgColor.fgWhite60),
+ ),
+ const Expanded(
+ child: RiveAssetAnimation(
+ "assets/next/rive/open_id.riv",
+ ),
),
- const Spacer(),
DgButton(
text: 'Cancel',
style: DgButtonStyle.outlined,
diff --git a/client/lib/open/screens/add_instance/screens/add_instance_form.dart b/client/lib/open/screens/add_instance/screens/add_instance_form.dart
index 09d07e2..b80b0ab 100644
--- a/client/lib/open/screens/add_instance/screens/add_instance_form.dart
+++ b/client/lib/open/screens/add_instance/screens/add_instance_form.dart
@@ -181,6 +181,10 @@ Future _handleSubmit(
final requestData = EnrollmentStartRequest(token: token);
final uri = Uri.parse(url);
final enrolmentResponse = await proxyApi.startEnrollment(uri, requestData);
+ if (!enrolmentResponse.user.enrolled) {
+ toaster.showError(message: "Only enrolled users can add devices.");
+ return;
+ }
final instanceId = enrolmentResponse.instance.id;
final dbInstance = await db.managers.defguardInstances
.filter((row) => row.uuid.equals(instanceId))
diff --git a/client/lib/open/screens/add_instance/screens/add_instance_qr_screen.dart b/client/lib/open/screens/add_instance/screens/add_instance_qr_screen.dart
index cfa49cf..c101649 100644
--- a/client/lib/open/screens/add_instance/screens/add_instance_qr_screen.dart
+++ b/client/lib/open/screens/add_instance/screens/add_instance_qr_screen.dart
@@ -40,6 +40,14 @@ class AddInstanceQrScreen extends HookConsumerWidget {
url,
requestData,
);
+ if (!registrationResponse.user.enrolled) {
+ toaster.showError(
+ message: "Only enrolled users can add devices.",
+ );
+ isLoading.value = false;
+ await controller.resume();
+ return;
+ }
final instanceId = registrationResponse.instance.id;
final dbInstance = await db.managers.defguardInstances
.filter((row) => row.uuid.equals(instanceId))
diff --git a/client/lib/open/screens/instance/instance_screen.dart b/client/lib/open/screens/instance/instance_screen.dart
index 9f38415..f0701fa 100644
--- a/client/lib/open/screens/instance/instance_screen.dart
+++ b/client/lib/open/screens/instance/instance_screen.dart
@@ -12,11 +12,11 @@ import 'package:mobile/open/api.dart';
import 'package:mobile/open/riverpod/biometrics_state.dart';
import 'package:mobile/open/riverpod/plugin/plugin.dart';
import 'package:mobile/open/screens/add_instance/data_gathering_dialog.dart';
+import 'package:mobile/open/screens/instance/refresh_instance_screen.dart';
import 'package:mobile/open/screens/instance/services/tunnel_service.dart';
import 'package:mobile/open/screens/instance/widgets/connect_dialog.dart';
import 'package:mobile/open/screens/instance/widgets/connection_conflict_dialog.dart';
import 'package:mobile/open/screens/instance/widgets/delete_instance_dialog.dart';
-import 'package:mobile/open/screens/instance/widgets/refresh_instance_dialog.dart';
import 'package:mobile/open/screens/mfa/remote_mfa_qr_screen.dart';
import 'package:mobile/open/widgets/dg_app_bar.dart';
import 'package:mobile/open/widgets/dg_bottom_sheet.dart';
@@ -364,11 +364,9 @@ class _InstanceAppBar extends ConsumerWidget implements PreferredSizeWidget {
onTap: () {
final instance = screenDataAsync.value?.instance;
if (instance == null) return;
- showDialog(
- context: context,
- builder: (context) =>
- RefreshInstanceDialog(instance: instance),
- );
+ RefreshInstanceScreenRoute(
+ RefreshInstanceScreenData(instance: instance),
+ ).push(context);
},
),
DgMenuItem(
diff --git a/client/lib/open/screens/instance/refresh_instance_screen.dart b/client/lib/open/screens/instance/refresh_instance_screen.dart
new file mode 100644
index 0000000..7061b8e
--- /dev/null
+++ b/client/lib/open/screens/instance/refresh_instance_screen.dart
@@ -0,0 +1,205 @@
+import 'package:flutter_hooks/flutter_hooks.dart';
+import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:material_ui/material_ui.dart';
+import 'package:mobile/data/db/database.dart';
+import 'package:mobile/data/proxy/enrollment.dart';
+import 'package:mobile/logging.dart';
+import 'package:mobile/open/api.dart';
+import 'package:mobile/open/widgets/dg_app_bar.dart';
+import 'package:mobile/open/widgets/dg_button.dart';
+import 'package:mobile/open/widgets/dg_icon_button.dart';
+import 'package:mobile/open/widgets/dg_text_form_field.dart';
+import 'package:mobile/open/widgets/toaster/toast_manager.dart';
+import 'package:mobile/theme/color.dart';
+import 'package:mobile/theme/spacing.dart';
+import 'package:mobile/theme/text.dart';
+import 'package:mobile/utils/update_instance.dart';
+
+class RefreshInstanceScreenData {
+ final DefguardInstance instance;
+
+ const RefreshInstanceScreenData({required this.instance});
+}
+
+class RefreshInstanceScreen extends StatelessWidget {
+ final DefguardInstance instance;
+
+ const RefreshInstanceScreen({super.key, required this.instance});
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ extendBodyBehindAppBar: true,
+ appBar: DgAppBar(
+ context: context,
+ showLogo: false,
+ actionLeft: DgIconButton(
+ icon: "close",
+ onTap: () => Navigator.of(context).pop(),
+ ),
+ ),
+ body: Container(
+ decoration: const BoxDecoration(gradient: DgColor.gradientPrimary),
+ child: SafeArea(child: _RefreshInstanceContent(instance: instance)),
+ ),
+ );
+ }
+}
+
+class _RefreshInstanceContent extends HookConsumerWidget {
+ final DefguardInstance instance;
+
+ const _RefreshInstanceContent({required this.instance});
+
+ @override
+ Widget build(BuildContext context, WidgetRef ref) {
+ final db = ref.read(databaseProvider);
+ final toaster = ref.read(toastManagerProvider.notifier);
+ final formKey = useMemoized(() => GlobalKey());
+ final tokenController = useTextEditingController();
+ final urlController = useTextEditingController(text: instance.proxyUrl);
+ final isLoading = useState(false);
+
+ String? validateUrl(String? value) {
+ if (value == null || value.trim().isEmpty) {
+ return "This field is required";
+ }
+ if (!_isValidUri(value.trim())) {
+ return "Enter valid URL";
+ }
+ return null;
+ }
+
+ Future submit() async {
+ if (!(formKey.currentState?.validate() ?? false)) return;
+ isLoading.value = true;
+ try {
+ final refreshed = await _refreshInstance(
+ db,
+ toaster,
+ instance,
+ Uri.parse(urlController.text.trim()),
+ tokenController.text.trim(),
+ );
+ if (refreshed && context.mounted) {
+ Navigator.of(context).pop();
+ }
+ } finally {
+ if (context.mounted) isLoading.value = false;
+ }
+ }
+
+ return Form(
+ key: formKey,
+ child: CustomScrollView(
+ slivers: [
+ SliverPadding(
+ padding: const .fromLTRB(20, 12, 20, 0),
+ sliver: SliverList(
+ delegate: SliverChildListDelegate([
+ Semantics(
+ identifier: "refresh_instance_header",
+ child: Text(
+ "Refresh Instance",
+ style: DgText.h4.copyWith(color: DgColor.fgWhite100),
+ textAlign: .left,
+ ),
+ ),
+ const SizedBox(height: DgSpacing.sm),
+ Text(
+ "Enter your proxy URL and instance token to refresh the configuration.",
+ style: DgText.bodySm400.copyWith(color: DgColor.fgWhite60),
+ textAlign: .left,
+ ),
+ const SizedBox(height: DgSpacing.xl3),
+ DgTextFormField(
+ identifier: "refresh_instance_token",
+ size: .big,
+ controller: tokenController,
+ label: "Token",
+ required: true,
+ hintText: "Instance token",
+ validator: (v) => v == null || v.trim().isEmpty
+ ? "This field is required"
+ : null,
+ ),
+ const SizedBox(height: DgSpacing.xl),
+ DgTextFormField(
+ identifier: "refresh_instance_url",
+ size: .big,
+ controller: urlController,
+ label: "URL",
+ required: true,
+ hintText: "Proxy URL",
+ keyboardType: .url,
+ validator: validateUrl,
+ ),
+ ]),
+ ),
+ ),
+ SliverFillRemaining(
+ hasScrollBody: false,
+ child: Padding(
+ padding: const .fromLTRB(20, 0, 20, 20),
+ child: Align(
+ alignment: .bottomCenter,
+ child: DgButton(
+ identifier: "refresh_instance_submit",
+ text: "Refresh",
+ style: .primary,
+ size: .big,
+ width: double.infinity,
+ loading: isLoading.value,
+ onTap: submit,
+ ),
+ ),
+ ),
+ ),
+ ],
+ ),
+ );
+ }
+}
+
+bool _isValidUri(String value) {
+ final uri = Uri.tryParse(value);
+ return uri != null && uri.hasScheme && uri.hasAuthority;
+}
+
+Future _refreshInstance(
+ AppDatabase db,
+ ToastManager toaster,
+ DefguardInstance instance,
+ Uri uri,
+ String token,
+) async {
+ talker.debug("Submitting instance refresh form");
+ try {
+ // this is only for dio to capture cookies required for network info call
+ await proxyApi.startEnrollment(uri, EnrollmentStartRequest(token: token));
+ final networkInfo = await proxyApi.networkInfo(uri, instance.pubKey);
+ talker.debug("Retrieved new instance information from proxy");
+ final updateResult = await updateInstance(
+ db: db,
+ instance: instance,
+ configs: networkInfo.configs,
+ info: networkInfo.instance,
+ token: networkInfo.token,
+ );
+ if (updateResult != null && updateResult.didChange) {
+ final message = getInstanceUpdateMessage(instance.name, updateResult);
+ toaster.show(message: "Instance ${instance.name} updated: $message");
+ } else {
+ toaster.show(message: "Instance information refreshed");
+ }
+ talker.info("Instance information refreshed successfully");
+ return true;
+ } catch (e, st) {
+ toaster.showError(
+ message: "Failed to refresh instance information",
+ error: e,
+ stackTrace: st,
+ );
+ return false;
+ }
+}
diff --git a/client/lib/open/screens/instance/widgets/refresh_instance_dialog.dart b/client/lib/open/screens/instance/widgets/refresh_instance_dialog.dart
deleted file mode 100644
index 415dc85..0000000
--- a/client/lib/open/screens/instance/widgets/refresh_instance_dialog.dart
+++ /dev/null
@@ -1,125 +0,0 @@
-import 'package:flutter_hooks/flutter_hooks.dart';
-import 'package:hooks_riverpod/hooks_riverpod.dart';
-import 'package:material_ui/material_ui.dart';
-import 'package:mobile/data/db/database.dart';
-import 'package:mobile/data/proxy/enrollment.dart';
-import 'package:mobile/logging.dart';
-import 'package:mobile/open/api.dart';
-import 'package:mobile/open/widgets/dg_button.dart';
-import 'package:mobile/open/widgets/dg_dialog.dart';
-import 'package:mobile/open/widgets/dg_text_form_field.dart';
-import 'package:mobile/open/widgets/toaster/toast_manager.dart';
-import 'package:mobile/theme/spacing.dart';
-import 'package:mobile/utils/update_instance.dart';
-
-class RefreshInstanceDialog extends HookConsumerWidget {
- final DefguardInstance instance;
-
- const RefreshInstanceDialog({super.key, required this.instance});
-
- @override
- Widget build(BuildContext context, WidgetRef ref) {
- final db = ref.read(databaseProvider);
- final toaster = ref.read(toastManagerProvider.notifier);
- final proxyUrlController = useTextEditingController(
- text: instance.proxyUrl,
- );
- final tokenController = useTextEditingController();
- final isLoading = useState(false);
-
- final submit = useCallback(() async {
- final url = proxyUrlController.text;
- final token = tokenController.text;
- final uri = Uri.parse(url);
- talker.debug("Submitting instance refresh form");
-
- try {
- // this is only for dio to capture cookies required for network info call
- await proxyApi.startEnrollment(
- uri,
- EnrollmentStartRequest(token: token),
- );
- final networkInfo = await proxyApi.networkInfo(uri, instance.pubKey);
- talker.debug("Retrieved new instance information from proxy");
- talker.debug("Updating instance info in DB");
- final updateResult = await updateInstance(
- db: db,
- instance: instance,
- configs: networkInfo.configs,
- info: networkInfo.instance,
- token: networkInfo.token,
- );
- if (updateResult != null && updateResult.didChange) {
- final message = getInstanceUpdateMessage(instance.name, updateResult);
- toaster.show(
- message: "Instance ${instance.name} updated: $message",
- );
- } else {
- toaster.show(message: "Instance information refreshed");
- }
- talker.info("Instance information refreshed successfully");
- } catch (e) {
- toaster.showError(
- message: "Failed to refresh instance information",
- error: e,
- );
- rethrow;
- }
- }, [db, toaster, proxyUrlController, tokenController, isLoading]);
-
- return DgDialog(
- onClose: () => Navigator.of(context).pop(),
- children: [
- const DgDialogTitle("Refresh Instance"),
- const DgDialogDescription(
- "Enter your proxy URL and instance token to refresh the configuration.",
- ),
- DgTextFormField(
- identifier: "refresh_instance_url",
- controller: proxyUrlController,
- label: "Proxy URL",
- hintText: "https://...",
- ),
- const SizedBox(height: DgSpacing.md),
- DgTextFormField(
- identifier: "refresh_instance_token",
- controller: tokenController,
- label: "Instance Token",
- hintText: "Enter token",
- ),
- const SizedBox(height: DgSpacing.xl2),
- Row(
- spacing: DgSpacing.md,
- children: [
- Expanded(
- child: DgButton(
- text: "Cancel",
- style: DgButtonStyle.secondary,
- onTap: () => Navigator.of(context).pop(),
- ),
- ),
- Expanded(
- child: DgButton(
- identifier: "refresh_instance_submit",
- text: "Refresh",
- style: DgButtonStyle.primary,
- loading: isLoading.value,
- onTap: () async {
- isLoading.value = true;
- try {
- await submit();
- if (context.mounted) {
- Navigator.of(context).pop();
- }
- } finally {
- isLoading.value = false;
- }
- },
- ),
- ),
- ],
- ),
- ],
- );
- }
-}
diff --git a/client/lib/open/widgets/dg_instance_card.dart b/client/lib/open/widgets/dg_instance_card.dart
index 3a4b66c..2caa6c2 100644
--- a/client/lib/open/widgets/dg_instance_card.dart
+++ b/client/lib/open/widgets/dg_instance_card.dart
@@ -1,5 +1,6 @@
-import 'package:material_ui/material_ui.dart';
import 'package:flutter/widget_previews.dart';
+import 'package:flutter_svg/flutter_svg.dart';
+import 'package:material_ui/material_ui.dart';
import 'package:mobile/open/widgets/dg_preview_wrapper.dart';
import 'package:mobile/theme/color.dart';
import 'package:mobile/theme/spacing.dart';
@@ -22,7 +23,9 @@ class DgInstanceCard extends StatelessWidget {
});
bool get isConnected => connectedCount != 0;
- String get icon => isConnected ? "connected_devices" : "device_ip";
+ String get icon => isConnected
+ ? "assets/next/img/connected_instance.svg"
+ : "assets/next/img/idle_instance.svg";
@override
Widget build(BuildContext context) {
@@ -38,19 +41,10 @@ class DgInstanceCard extends StatelessWidget {
crossAxisAlignment: .center,
mainAxisAlignment: .start,
children: [
- Container(
+ SizedBox(
height: 48,
width: 48,
- alignment: .center,
- decoration: BoxDecoration(
- borderRadius: .circular(14),
- color: isConnected ? DgColor.bgWhite100 : DgColor.bgDarkBlue20,
- ),
- child: DgIcon(
- icon,
- size: 24,
- color: isConnected ? DgColor.fgAction : DgColor.fgWhite60,
- ),
+ child: SvgPicture.asset(icon),
),
SizedBox(width: DgSpacing.xl),
Expanded(
diff --git a/client/lib/open/widgets/dg_location_card.dart b/client/lib/open/widgets/dg_location_card.dart
index 509d489..c463beb 100644
--- a/client/lib/open/widgets/dg_location_card.dart
+++ b/client/lib/open/widgets/dg_location_card.dart
@@ -306,43 +306,39 @@ class _InnerInfoCard extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
- padding: const EdgeInsets.symmetric(
- vertical: DgSpacing.sm,
- horizontal: DgSpacing.md,
- ),
+ padding: const .all(DgSpacing.md),
decoration: BoxDecoration(
color: DgColor.bgWhite5,
- borderRadius: BorderRadius.circular(12),
+ borderRadius: .circular(12),
),
- child: Row(
- mainAxisAlignment: MainAxisAlignment.start,
- crossAxisAlignment: CrossAxisAlignment.center,
- spacing: DgSpacing.md,
+ child: Column(
+ mainAxisSize: .min,
+ crossAxisAlignment: .start,
children: [
Container(
decoration: BoxDecoration(
- borderRadius: BorderRadius.circular(8),
+ borderRadius: .circular(6),
color: DgColor.bgWhite10,
),
- width: 36,
- height: 36,
- alignment: Alignment.center,
+ width: 24,
+ height: 24,
+ alignment: .center,
child: getIcon(),
),
- Column(
- mainAxisAlignment: MainAxisAlignment.center,
- crossAxisAlignment: CrossAxisAlignment.start,
- spacing: 2,
- children: [
- Text(
- getLabel(),
- style: DgText.bodyXxs400.copyWith(color: DgColor.fgWhite50),
- ),
- Text(
- getText(),
- style: DgText.bodyXs500.copyWith(color: getTextColor()),
- ),
- ],
+ const SizedBox(height: DgSpacing.md),
+ Text(
+ getLabel(),
+ style: DgText.bodyXxs400.copyWith(color: DgColor.fgWhite50),
+ ),
+ const SizedBox(height: 2),
+ FittedBox(
+ fit: .scaleDown,
+ alignment: .centerLeft,
+ child: Text(
+ getText(),
+ maxLines: 1,
+ style: DgText.bodyXs500.copyWith(color: getTextColor()),
+ ),
),
],
),
@@ -379,17 +375,17 @@ class _InnerInfoCard extends StatelessWidget {
break;
}
}
- return DgIcon(iconFileName, size: 20, color: iconColor);
+ return DgIcon(iconFileName, size: 16, color: iconColor);
}
String getLabel() {
if (isMfa) {
- return "MFA";
+ return "Active MFA";
}
if (isRouting) {
- return "Traffic";
+ return "Allowed traffic";
}
- return "MFA";
+ return "Active MFA";
}
String getText() {
diff --git a/client/lib/open/widgets/dg_openid_mfa_layout.dart b/client/lib/open/widgets/dg_openid_mfa_layout.dart
index 8506174..2f8976d 100644
--- a/client/lib/open/widgets/dg_openid_mfa_layout.dart
+++ b/client/lib/open/widgets/dg_openid_mfa_layout.dart
@@ -64,8 +64,10 @@ class DgOpenIdMfaLayout extends StatelessWidget {
"Confirm your identity to continue. You'll be redirected to your identity provider to complete verification.",
style: DgText.bodySm400.copyWith(color: DgColor.fgWhite60),
),
- Expanded(
- child: RiveAssetAnimation("assets/next/rive/openid_mfa.riv"),
+ const Expanded(
+ child: RiveAssetAnimation(
+ "assets/next/rive/open_id.riv",
+ ),
),
DgExternalProviderButton(
text: 'Continue with $providerName',
diff --git a/client/lib/router/routes.dart b/client/lib/router/routes.dart
index 770f6aa..7a86224 100644
--- a/client/lib/router/routes.dart
+++ b/client/lib/router/routes.dart
@@ -7,6 +7,7 @@ import 'package:mobile/open/screens/add_instance/screens/biometry/biometry_finis
import 'package:mobile/open/screens/add_instance/screens/biometry/biometry_setup_failed_screen.dart';
import 'package:mobile/open/screens/add_instance/screens/biometry/biometry_setup_screen.dart';
import 'package:mobile/open/screens/add_instance/screens/name_device_screen.dart';
+import 'package:mobile/open/screens/instance/refresh_instance_screen.dart';
import 'package:mobile/open/screens/instances_list/instances_list_screen.dart';
import 'package:mobile/open/screens/mfa/remote_mfa_qr_screen.dart';
import 'package:mobile/open/screens/splash.dart';
@@ -85,6 +86,20 @@ class InstanceScreenRoute extends GoRouteData with $InstanceScreenRoute {
}
}
+@TypedGoRoute(path: "/refresh_instance")
+@immutable
+class RefreshInstanceScreenRoute extends GoRouteData
+ with $RefreshInstanceScreenRoute {
+ const RefreshInstanceScreenRoute(this.$extra);
+
+ final RefreshInstanceScreenData $extra;
+
+ @override
+ Widget build(BuildContext context, GoRouterState state) {
+ return RefreshInstanceScreen(instance: $extra.instance);
+ }
+}
+
@TypedGoRoute(path: "/add_instance/name_device")
@immutable
class NameDeviceScreenRoute extends GoRouteData with $NameDeviceScreenRoute {
diff --git a/client/lib/router/routes.g.dart b/client/lib/router/routes.g.dart
index 5e45d8f..4f91a2a 100644
--- a/client/lib/router/routes.g.dart
+++ b/client/lib/router/routes.g.dart
@@ -12,6 +12,7 @@ List get $appRoutes => [
$addInstanceQrScreenRoute,
$remoteMfaQrScreenRoute,
$instanceScreenRoute,
+ $refreshInstanceScreenRoute,
$nameDeviceScreenRoute,
$addInstanceFormScreenRoute,
$addInstanceScreenRoute,
@@ -253,6 +254,37 @@ mixin $BiometryFinishScreenRoute on GoRouteData {
void replace(BuildContext context) => context.replace(location);
}
+RouteBase get $refreshInstanceScreenRoute => GoRouteData.$route(
+ path: '/refresh_instance',
+ hasOverriddenOnExit: false,
+ factory: $RefreshInstanceScreenRoute._fromState,
+);
+
+mixin $RefreshInstanceScreenRoute on GoRouteData {
+ static RefreshInstanceScreenRoute _fromState(GoRouterState state) =>
+ RefreshInstanceScreenRoute(state.extra as RefreshInstanceScreenData);
+
+ RefreshInstanceScreenRoute get _self => this as RefreshInstanceScreenRoute;
+
+ @override
+ String get location => GoRouteData.$location('/refresh_instance');
+
+ @override
+ void go(BuildContext context) => context.go(location, extra: _self.$extra);
+
+ @override
+ Future push(BuildContext context) =>
+ context.push(location, extra: _self.$extra);
+
+ @override
+ void pushReplacement(BuildContext context) =>
+ context.pushReplacement(location, extra: _self.$extra);
+
+ @override
+ void replace(BuildContext context) =>
+ context.replace(location, extra: _self.$extra);
+}
+
RouteBase get $nameDeviceScreenRoute => GoRouteData.$route(
path: '/add_instance/name_device',
hasOverriddenOnExit: false,
diff --git a/e2e/helpers/coreApi.ts b/e2e/helpers/coreApi.ts
index 98a5fe5..8f5f048 100644
--- a/e2e/helpers/coreApi.ts
+++ b/e2e/helpers/coreApi.ts
@@ -74,6 +74,7 @@ export class CoreApi {
first_name: "E2E",
last_name: "Test",
email: `${username}@e2e.test`,
+ password: generatePassword(),
});
}
@@ -145,13 +146,13 @@ export class CoreApi {
return secret;
}
- async startEnrollment(
+ async startDesktopConfiguration(
username: string,
ephemeral = false,
): Promise {
const response = await this.request(
"POST",
- `/api/v1/user/${username}/start_enrollment`,
+ `/api/v1/user/${username}/start_desktop`,
{
send_enrollment_notification: false,
},
@@ -172,7 +173,7 @@ export class CoreApi {
await this.deleteUser(username);
}
await this.createUser(username);
- return this.startEnrollment(username, !pinned);
+ return this.startDesktopConfiguration(username, !pinned);
}
}
diff --git a/e2e/tests/instance-refresh.spec.ts b/e2e/tests/instance-refresh.spec.ts
index 9ace921..6f8364b 100644
--- a/e2e/tests/instance-refresh.spec.ts
+++ b/e2e/tests/instance-refresh.spec.ts
@@ -26,7 +26,9 @@ describe("instance refresh", () => {
await completeEnrollment(fixture);
await waitForInstanceScreen();
- await refreshInstance(await core.startEnrollment(fixture.username));
+ await refreshInstance(
+ await core.startDesktopConfiguration(fixture.username),
+ );
await waitForInstanceScreen();
});
});