Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .fvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"flutter": "3.38.10"
}
3 changes: 2 additions & 1 deletion client/lib/data/db/enums.dart
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ enum ClientTrafficPolicy {
ClientTrafficPolicy.values.firstWhere((e) => e.value == value);
}

class ClientTrafficPolicyConverter extends TypeConverter<ClientTrafficPolicy, int> {
class ClientTrafficPolicyConverter
extends TypeConverter<ClientTrafficPolicy, int> {
const ClientTrafficPolicyConverter();

@override
Expand Down
6 changes: 3 additions & 3 deletions client/lib/data/proxy/config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ class NetworkInfoResponse {
this.token,
});

factory NetworkInfoResponse.fromJson(Map<String, dynamic> json) =>
_$NetworkInfoResponseFromJson(json);
factory NetworkInfoResponse.fromJson(Map<String, dynamic> json) =>
_$NetworkInfoResponseFromJson(json);

Map<String, dynamic> toJson() => _$NetworkInfoResponseToJson(this);
Map<String, dynamic> toJson() => _$NetworkInfoResponseToJson(this);
}
27 changes: 10 additions & 17 deletions client/lib/enterprise/config_update.dart
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,7 @@ class ConfigurationUpdater extends HookConsumerWidget {
);
for (final instance in instances) {
talker.debug(
"Auto configuration update started for ${instance.name} (${instance
.id})",
"Auto configuration update started for ${instance.name} (${instance.id})",
);
final (responseData, responseStatus, headers) = await proxyApi
.pollConfiguration(instance.proxyUrl, instance.poolingToken);
Expand All @@ -61,8 +60,7 @@ class ConfigurationUpdater extends HookConsumerWidget {
headers['defguard-component-version']?.first;
if (coreVersionStr == null || proxyVersionStr == null) {
talker.error(
"Version headers missing for ${instance
.logName}, treating as unsupported",
"Version headers missing for ${instance.logName}, treating as unsupported",
);
versionUnsupportedInstances.add({
'name': instance.name,
Expand Down Expand Up @@ -95,9 +93,7 @@ class ConfigurationUpdater extends HookConsumerWidget {
}
if (responseData == null) {
talker.error(
"Auto configuration update failed for ${instance
.logName} ! Update data retrieval failed, status: ${responseStatus ??
"unknown"}!",
"Auto configuration update failed for ${instance.logName} ! Update data retrieval failed, status: ${responseStatus ?? "unknown"}!",
);
continue;
}
Expand All @@ -112,12 +108,7 @@ class ConfigurationUpdater extends HookConsumerWidget {
);
if (updateResult != null) {
talker.info(
"Instance ${instance
.logName} results: Instance updated: ${updateResult
.instanceChanged} | Locations updated: ${updateResult
.locationsUpdated} | Locations removed: ${updateResult
.locationsRemoved} | Locations added: ${updateResult
.locationsAdded}",
"Instance ${instance.logName} results: Instance updated: ${updateResult.instanceChanged} | Locations updated: ${updateResult.locationsUpdated} | Locations removed: ${updateResult.locationsRemoved} | Locations added: ${updateResult.locationsAdded}",
);
if (updateResult.didChange) {
final message = getInstanceUpdateMessage(
Expand All @@ -144,7 +135,7 @@ class ConfigurationUpdater extends HookConsumerWidget {
"The following instances have versions that are incompatible with your Defguard Mobile Client and may not work correctly:\n\n";
for (final instance in versionUnsupportedInstances) {
message +=
"- ${instance['name']}: Defguard Core ${instance['coreVersion']} (expected >=$supportedCoreVersion), Defguard Proxy ${instance['proxyVersion']} (expected >=$supportedProxyVersion)\n";
"- ${instance['name']}: Defguard Core ${instance['coreVersion']} (expected >=$supportedCoreVersion), Defguard Proxy ${instance['proxyVersion']} (expected >=$supportedProxyVersion)\n";
}
message += "\nPlease contact your administrator.";
toaster.showInfo(
Expand All @@ -170,10 +161,12 @@ class ConfigurationUpdater extends HookConsumerWidget {
// update when user wakes up application
useEffect(() {
final timeTick = DateTime.now();
final afterCooldown = lastConfigUpdate.value == null ||
final afterCooldown =
lastConfigUpdate.value == null ||
(lastConfigUpdate.value != null &&
lastConfigUpdate.value!.add(Duration(seconds: 60)).isBefore(
timeTick));
lastConfigUpdate.value!
.add(Duration(seconds: 60))
.isBefore(timeTick));
if (lifecycle == AppLifecycleState.resumed && afterCooldown) {
lastConfigUpdate.value = timeTick;
updateConfiguration();
Expand Down
11 changes: 11 additions & 0 deletions client/lib/enterprise/postures.dart
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ class DevicePostureData {
final Int32Check? windowsSecurityUpdateAgeDays;
final StringCheck? linuxKernelVersion;
final BoolCheck? deviceIntegrity;
final StringCheck? androidSecurityPatchDate;

const DevicePostureData({
required this.defguardClientVersion,
Expand All @@ -93,6 +94,7 @@ class DevicePostureData {
this.windowsSecurityUpdateAgeDays,
this.linuxKernelVersion,
this.deviceIntegrity,
this.androidSecurityPatchDate,
});

factory DevicePostureData.fromJson(Map<String, dynamic> json) =>
Expand Down Expand Up @@ -158,6 +160,9 @@ Future<DevicePostureData> getPosture() async {
linuxKernelVersion: StringCheck.unavailable(
UnavailableReason.notApplicable,
),
androidSecurityPatchDate: android.version.securityPatch != null
? StringCheck.value(android.version.securityPatch!)
: StringCheck.unavailable(UnavailableReason.detectionFailed),
);
}

Expand All @@ -182,6 +187,9 @@ Future<DevicePostureData> getPosture() async {
linuxKernelVersion: StringCheck.unavailable(
UnavailableReason.notApplicable,
),
androidSecurityPatchDate: StringCheck.unavailable(
UnavailableReason.notApplicable,
),
);
}

Expand All @@ -203,5 +211,8 @@ Future<DevicePostureData> getPosture() async {
UnavailableReason.notApplicable,
),
deviceIntegrity: BoolCheck.unavailable(UnavailableReason.notApplicable),
androidSecurityPatchDate: StringCheck.unavailable(
UnavailableReason.notApplicable,
),
);
}
8 changes: 8 additions & 0 deletions client/lib/enterprise/postures.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion client/lib/logging.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import 'package:talker_flutter/talker_flutter.dart';

final talker = TalkerFlutter.init();
final talker = TalkerFlutter.init();
25 changes: 16 additions & 9 deletions client/lib/open/api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@ import 'package:cookie_jar/cookie_jar.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:dio/dio.dart';
import 'package:dio_cookie_manager/dio_cookie_manager.dart';
import 'package:native_dio_adapter/native_dio_adapter.dart';
import 'package:mobile/data/db/enums.dart';
import 'package:mobile/data/proto/client_platform_info.pb.dart';
import 'package:mobile/data/proxy/config.dart';
import 'package:mobile/enterprise/postures.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:mobile/data/proxy/enrollment.dart';
import 'package:mobile/data/proxy/mfa.dart';

import 'package:mobile/enterprise/postures.dart';
import 'package:native_dio_adapter/native_dio_adapter.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:talker_dio_logger/talker_dio_logger_interceptor.dart';

import '../logging.dart';
Expand Down Expand Up @@ -211,6 +210,13 @@ class _ProxyApi {
dataError.toLowerCase().trim() == missingMFAMethodError) {
throw MfaMethodNotAvailableException(data.method);
}

if (e.response?.statusCode == 403) {
final error = responseData['error'] ?? responseData['message'];
if (error is String) {
throw HttpException(error);
}
}
}
throw HttpException(
"Failed to start MFA. Status: ${e.response?.statusCode} Body: ${e.response?.data}",
Expand All @@ -237,11 +243,12 @@ class _ProxyApi {
return PostureConnectResponse.fromJson(response.data);
} on DioException catch (e) {
final responseData = e.response?.data;
final dataError = responseData is Map<String, dynamic>
? responseData['error']
: null;
if (e.response?.statusCode == 403 && dataError is String) {
throw PostureCheckException(dataError);
if (e.response?.statusCode == 403 &&
responseData is Map<String, dynamic>) {
final error = responseData['error'] ?? responseData['message'];
if (error is String) {
throw PostureCheckException(error);
}
}
if (e.response != null) {
throw HttpException(
Expand Down
1 change: 0 additions & 1 deletion client/lib/open/riverpod/biometrics_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import 'package:riverpod_annotation/riverpod_annotation.dart';

part 'biometrics_state.g.dart';


class BiometricsState {
bool isSupported;
bool canCheck;
Expand Down
2 changes: 1 addition & 1 deletion client/lib/open/riverpod/package_info/package_info.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ Future<PackageInfo> packageInfo(Ref ref) async {
WidgetsFlutterBinding.ensureInitialized();
final info = await PackageInfo.fromPlatform();
return info;
}
}
2 changes: 1 addition & 1 deletion client/lib/open/riverpod/plugin/plugin.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ class PluginActiveTunnelState extends _$PluginActiveTunnelState {
void clear() {
state = null;
}
}
}
6 changes: 1 addition & 5 deletions client/lib/open/screens/add_instance/generate_wireguard.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,10 @@ import 'dart:convert';
import 'package:mobile/data/proxy/enrollment.dart';
import 'package:x25519/x25519.dart' as x;


Future<WireguardEncodedKeyPair> generateWireguardKeyPair() async {
final keyPair = x.generateKeyPair();
final encodedPriv = base64Encode(keyPair.privateKey);
final encodedPub = base64Encode(keyPair.publicKey);

return WireguardEncodedKeyPair(
privKey: encodedPriv,
pubKey: encodedPub,
);
return WireguardEncodedKeyPair(privKey: encodedPriv, pubKey: encodedPub);
}
28 changes: 14 additions & 14 deletions client/lib/open/screens/instance/instance_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -415,20 +415,20 @@ class _LocationItem extends HookConsumerWidget {
);
},
),
if (instance.clientTrafficPolicy == ClientTrafficPolicy.none)
DgMenuItem(
text: "Select Traffic Routing",
onTap: () {
showDialog(
context: context,
builder: (_) => RoutingMethodDialog(
location: location,
intention: RoutingMethodDialogIntention.save,
clientTrafficPolicy: instance.clientTrafficPolicy,
),
);
},
),
if (instance.clientTrafficPolicy == ClientTrafficPolicy.none)
DgMenuItem(
text: "Select Traffic Routing",
onTap: () {
showDialog(
context: context,
builder: (_) => RoutingMethodDialog(
location: location,
intention: RoutingMethodDialogIntention.save,
clientTrafficPolicy: instance.clientTrafficPolicy,
),
);
},
),
];
}, [location, instance]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import 'package:mobile/utils/secure_storage.dart';

import '../../../services/snackbar_service.dart';


class DeleteInstanceDialog extends HookConsumerWidget {
final DefguardInstance instance;

Expand All @@ -25,7 +24,7 @@ class DeleteInstanceDialog extends HookConsumerWidget {

Future<void> deleteInstance(BuildContext context) async {
try {
if(instance.mfaKeysStored) {
if (instance.mfaKeysStored) {
await removeInstanceStorage(instance.secureStorageKey);
}
await db.managers.defguardInstances
Expand All @@ -35,8 +34,10 @@ class DeleteInstanceDialog extends HookConsumerWidget {
SnackbarService.show("Instance deleted");
Navigator.of(context).pop();
}
} catch(e) {
talker.error("Failed to delete instance ${instance.logName}! Reason: \n $e");
} catch (e) {
talker.error(
"Failed to delete instance ${instance.logName}! Reason: \n $e",
);
}
}

Expand Down
5 changes: 4 additions & 1 deletion client/lib/open/widgets/buttons/dg_text_button.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,10 @@ class DgTextButton extends StatelessWidget {
child: Text(
text,
textAlign: TextAlign.center,
style: textStyle.copyWith(decoration: TextDecoration.underline, decorationColor: textStyle.color),
style: textStyle.copyWith(
decoration: TextDecoration.underline,
decorationColor: textStyle.color,
),
),
),
),
Expand Down
2 changes: 1 addition & 1 deletion client/lib/open/widgets/dg_checkbox.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class DgCheckbox extends StatelessWidget {
Widget _getBody() {
final icon = DgIconCheckbox(size: iconSize, variant: _getIconVariant());
TextStyle textStyleInner;
if(textStyle == null) {
if (textStyle == null) {
textStyleInner = DgText.modal1.copyWith(color: DgColor.textBodySecondary);
} else {
textStyleInner = textStyle!;
Expand Down
12 changes: 8 additions & 4 deletions client/lib/open/widgets/dg_menu.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
Expand Down Expand Up @@ -31,7 +30,9 @@ class DgMenu extends HookConsumerWidget {

@override
Widget build(BuildContext context, WidgetRef ref) {
final topOffset = useMemoized(() => anchorGeometry.position.dy + 10 + anchorGeometry.size.height);
final topOffset = useMemoized(
() => anchorGeometry.position.dy + 10 + anchorGeometry.size.height,
);
final leftOffset = useMemoized(() => anchorGeometry.position.dx);
final animationController = useAnimationController(
duration: 100.ms,
Expand Down Expand Up @@ -67,8 +68,11 @@ class DgMenu extends HookConsumerWidget {
builder: (context, _) => FadeTransition(
opacity: animationController,
child: SlideTransition(
position: Tween<Offset>(begin: Offset(0, -0.05), end: Offset.zero)
.animate(
position:
Tween<Offset>(
begin: Offset(0, -0.05),
end: Offset.zero,
).animate(
CurvedAnimation(
parent: animationController,
curve: Curves.easeOut,
Expand Down
2 changes: 1 addition & 1 deletion client/lib/open/widgets/loading_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class LoadingView extends StatelessWidget {
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
DgCircularProgress(color: DgColor.iconSecondary, size: 92),
DgCircularProgress(color: DgColor.iconSecondary, size: 92),
],
),
);
Expand Down
Loading