|
@@ -1,5 +1,3 @@
|
|
|
-// @dart=2.9
|
|
|
-
|
|
|
import 'dart:async';
|
|
|
import 'dart:typed_data';
|
|
|
|
|
@@ -44,9 +42,9 @@ class UserService {
|
|
|
final _enteDio = Network.instance.enteDio;
|
|
|
final _logger = Logger((UserService).toString());
|
|
|
final _config = Configuration.instance;
|
|
|
- SharedPreferences _preferences;
|
|
|
+ late SharedPreferences _preferences;
|
|
|
|
|
|
- ValueNotifier<String> emailValueNotifier;
|
|
|
+ late ValueNotifier<String?> emailValueNotifier;
|
|
|
|
|
|
UserService._privateConstructor();
|
|
|
|
|
@@ -54,7 +52,7 @@ class UserService {
|
|
|
|
|
|
Future<void> init() async {
|
|
|
emailValueNotifier =
|
|
|
- ValueNotifier<String>(Configuration.instance.getEmail());
|
|
|
+ ValueNotifier<String?>(Configuration.instance.getEmail());
|
|
|
_preferences = await SharedPreferences.getInstance();
|
|
|
if (Configuration.instance.isLoggedIn()) {
|
|
|
// add artificial delay in refreshing 2FA status
|
|
@@ -82,7 +80,7 @@ class UserService {
|
|
|
data: {"email": email, "purpose": isChangeEmail ? "change" : ""},
|
|
|
);
|
|
|
await dialog.hide();
|
|
|
- if (response != null && response.statusCode == 200) {
|
|
|
+ if (response.statusCode == 200) {
|
|
|
unawaited(
|
|
|
Navigator.of(context).push(
|
|
|
MaterialPageRoute(
|
|
@@ -102,7 +100,7 @@ class UserService {
|
|
|
} on DioError catch (e) {
|
|
|
await dialog.hide();
|
|
|
_logger.info(e);
|
|
|
- if (e.response != null && e.response.statusCode == 403) {
|
|
|
+ if (e.response != null && e.response!.statusCode == 403) {
|
|
|
unawaited(
|
|
|
showErrorDialog(
|
|
|
context,
|
|
@@ -120,7 +118,7 @@ class UserService {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- Future<String> getPublicKey(String email) async {
|
|
|
+ Future<String?> getPublicKey(String email) async {
|
|
|
try {
|
|
|
final response = await _enteDio.get(
|
|
|
"/users/public-key",
|
|
@@ -135,9 +133,9 @@ class UserService {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- UserDetails getCachedUserDetails() {
|
|
|
+ UserDetails? getCachedUserDetails() {
|
|
|
if (_preferences.containsKey(keyUserDetails)) {
|
|
|
- return UserDetails.fromJson(_preferences.getString(keyUserDetails));
|
|
|
+ return UserDetails.fromJson(_preferences.getString(keyUserDetails)!);
|
|
|
}
|
|
|
return null;
|
|
|
}
|
|
@@ -204,7 +202,7 @@ class UserService {
|
|
|
await dialog.show();
|
|
|
try {
|
|
|
final response = await _enteDio.post("/users/logout");
|
|
|
- if (response != null && response.statusCode == 200) {
|
|
|
+ if (response.statusCode == 200) {
|
|
|
await Configuration.instance.logout();
|
|
|
await dialog.hide();
|
|
|
Navigator.of(context).popUntil((route) => route.isFirst);
|
|
@@ -218,14 +216,14 @@ class UserService {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- Future<DeleteChallengeResponse> getDeleteChallenge(
|
|
|
+ Future<DeleteChallengeResponse?> getDeleteChallenge(
|
|
|
BuildContext context,
|
|
|
) async {
|
|
|
final dialog = createProgressDialog(context, "Please wait...");
|
|
|
await dialog.show();
|
|
|
try {
|
|
|
final response = await _enteDio.get("/users/delete-challenge");
|
|
|
- if (response != null && response.statusCode == 200) {
|
|
|
+ if (response.statusCode == 200) {
|
|
|
// clear data
|
|
|
await dialog.hide();
|
|
|
return DeleteChallengeResponse(
|
|
@@ -254,7 +252,7 @@ class UserService {
|
|
|
"challenge": challengeResponse,
|
|
|
},
|
|
|
);
|
|
|
- if (response != null && response.statusCode == 200) {
|
|
|
+ if (response.statusCode == 200) {
|
|
|
// clear data
|
|
|
await Configuration.instance.logout();
|
|
|
} else {
|
|
@@ -278,10 +276,10 @@ class UserService {
|
|
|
},
|
|
|
);
|
|
|
await dialog.hide();
|
|
|
- if (response != null && response.statusCode == 200) {
|
|
|
+ if (response.statusCode == 200) {
|
|
|
Widget page;
|
|
|
final String twoFASessionID = response.data["twoFactorSessionID"];
|
|
|
- if (twoFASessionID != null && twoFASessionID.isNotEmpty) {
|
|
|
+ if (twoFASessionID.isNotEmpty) {
|
|
|
page = TwoFactorAuthenticationPage(twoFASessionID);
|
|
|
} else {
|
|
|
await _saveConfiguration(response);
|
|
@@ -306,7 +304,7 @@ class UserService {
|
|
|
} on DioError catch (e) {
|
|
|
_logger.info(e);
|
|
|
await dialog.hide();
|
|
|
- if (e.response != null && e.response.statusCode == 410) {
|
|
|
+ if (e.response != null && e.response!.statusCode == 410) {
|
|
|
await showErrorDialog(
|
|
|
context,
|
|
|
"Oops",
|
|
@@ -329,7 +327,7 @@ class UserService {
|
|
|
|
|
|
Future<void> setEmail(String email) async {
|
|
|
await _config.setEmail(email);
|
|
|
- emailValueNotifier.value = email ?? "";
|
|
|
+ emailValueNotifier.value = email;
|
|
|
}
|
|
|
|
|
|
Future<void> changeEmail(
|
|
@@ -348,7 +346,7 @@ class UserService {
|
|
|
},
|
|
|
);
|
|
|
await dialog.hide();
|
|
|
- if (response != null && response.statusCode == 200) {
|
|
|
+ if (response.statusCode == 200) {
|
|
|
showShortToast(context, "Email changed to " + email);
|
|
|
await setEmail(email);
|
|
|
Navigator.of(context).popUntil((route) => route.isFirst);
|
|
@@ -358,7 +356,7 @@ class UserService {
|
|
|
showErrorDialog(context, "Oops", "Verification failed, please try again");
|
|
|
} on DioError catch (e) {
|
|
|
await dialog.hide();
|
|
|
- if (e.response != null && e.response.statusCode == 403) {
|
|
|
+ if (e.response != null && e.response!.statusCode == 403) {
|
|
|
showErrorDialog(context, "Oops", "This email is already in use");
|
|
|
} else {
|
|
|
showErrorDialog(
|
|
@@ -418,8 +416,8 @@ class UserService {
|
|
|
final setRecoveryKeyRequest = SetRecoveryKeyRequest(
|
|
|
keyAttributes.masterKeyEncryptedWithRecoveryKey,
|
|
|
keyAttributes.masterKeyDecryptionNonce,
|
|
|
- keyAttributes.recoveryKeyEncryptedWithMasterKey,
|
|
|
- keyAttributes.recoveryKeyDecryptionNonce,
|
|
|
+ keyAttributes.recoveryKeyEncryptedWithMasterKey!,
|
|
|
+ keyAttributes.recoveryKeyDecryptionNonce!,
|
|
|
);
|
|
|
await _enteDio.put(
|
|
|
"/users/recovery-key",
|
|
@@ -448,7 +446,7 @@ class UserService {
|
|
|
},
|
|
|
);
|
|
|
await dialog.hide();
|
|
|
- if (response != null && response.statusCode == 200) {
|
|
|
+ if (response.statusCode == 200) {
|
|
|
showShortToast(context, "Authentication successful!");
|
|
|
await _saveConfiguration(response);
|
|
|
Navigator.of(context).pushAndRemoveUntil(
|
|
@@ -463,7 +461,7 @@ class UserService {
|
|
|
} on DioError catch (e) {
|
|
|
await dialog.hide();
|
|
|
_logger.severe(e);
|
|
|
- if (e.response != null && e.response.statusCode == 404) {
|
|
|
+ if (e.response != null && e.response!.statusCode == 404) {
|
|
|
showToast(context, "Session expired");
|
|
|
Navigator.of(context).pushAndRemoveUntil(
|
|
|
MaterialPageRoute(
|
|
@@ -501,7 +499,7 @@ class UserService {
|
|
|
"sessionID": sessionID,
|
|
|
},
|
|
|
);
|
|
|
- if (response != null && response.statusCode == 200) {
|
|
|
+ if (response.statusCode == 200) {
|
|
|
Navigator.of(context).pushAndRemoveUntil(
|
|
|
MaterialPageRoute(
|
|
|
builder: (BuildContext context) {
|
|
@@ -517,7 +515,7 @@ class UserService {
|
|
|
}
|
|
|
} on DioError catch (e) {
|
|
|
_logger.severe(e);
|
|
|
- if (e.response != null && e.response.statusCode == 404) {
|
|
|
+ if (e.response != null && e.response!.statusCode == 404) {
|
|
|
showToast(context, "Session expired");
|
|
|
Navigator.of(context).pushAndRemoveUntil(
|
|
|
MaterialPageRoute(
|
|
@@ -589,7 +587,7 @@ class UserService {
|
|
|
"secret": secret,
|
|
|
},
|
|
|
);
|
|
|
- if (response != null && response.statusCode == 200) {
|
|
|
+ if (response.statusCode == 200) {
|
|
|
showShortToast(context, "Two-factor authentication successfully reset");
|
|
|
await _saveConfiguration(response);
|
|
|
Navigator.of(context).pushAndRemoveUntil(
|
|
@@ -603,7 +601,7 @@ class UserService {
|
|
|
}
|
|
|
} on DioError catch (e) {
|
|
|
_logger.severe(e);
|
|
|
- if (e.response != null && e.response.statusCode == 404) {
|
|
|
+ if (e.response != null && e.response!.statusCode == 404) {
|
|
|
showToast(context, "Session expired");
|
|
|
Navigator.of(context).pushAndRemoveUntil(
|
|
|
MaterialPageRoute(
|
|
@@ -678,9 +676,9 @@ class UserService {
|
|
|
data: {
|
|
|
"code": code,
|
|
|
"encryptedTwoFactorSecret":
|
|
|
- Sodium.bin2base64(encryptionResult.encryptedData),
|
|
|
+ Sodium.bin2base64(encryptionResult.encryptedData as Uint8List),
|
|
|
"twoFactorSecretDecryptionNonce":
|
|
|
- Sodium.bin2base64(encryptionResult.nonce),
|
|
|
+ Sodium.bin2base64(encryptionResult.nonce as Uint8List),
|
|
|
},
|
|
|
);
|
|
|
await dialog.hide();
|
|
@@ -691,7 +689,7 @@ class UserService {
|
|
|
await dialog.hide();
|
|
|
_logger.severe(e, s);
|
|
|
if (e is DioError) {
|
|
|
- if (e.response != null && e.response.statusCode == 401) {
|
|
|
+ if (e.response != null && e.response!.statusCode == 401) {
|
|
|
showErrorDialog(
|
|
|
context,
|
|
|
"Incorrect code",
|
|
@@ -748,8 +746,8 @@ class UserService {
|
|
|
}
|
|
|
|
|
|
Future<Uint8List> getOrCreateRecoveryKey(BuildContext context) async {
|
|
|
- final encryptedRecoveryKey =
|
|
|
- _config.getKeyAttributes().recoveryKeyEncryptedWithMasterKey;
|
|
|
+ final String? encryptedRecoveryKey =
|
|
|
+ _config.getKeyAttributes()!.recoveryKeyEncryptedWithMasterKey;
|
|
|
if (encryptedRecoveryKey == null || encryptedRecoveryKey.isEmpty) {
|
|
|
final dialog = createProgressDialog(context, "Please wait...");
|
|
|
await dialog.show();
|
|
@@ -767,10 +765,10 @@ class UserService {
|
|
|
return recoveryKey;
|
|
|
}
|
|
|
|
|
|
- Future<String> getPaymentToken() async {
|
|
|
+ Future<String?> getPaymentToken() async {
|
|
|
try {
|
|
|
final response = await _enteDio.get("/users/payment-token");
|
|
|
- if (response != null && response.statusCode == 200) {
|
|
|
+ if (response.statusCode == 200) {
|
|
|
return response.data["paymentToken"];
|
|
|
} else {
|
|
|
throw Exception("non 200 ok response");
|
|
@@ -784,7 +782,7 @@ class UserService {
|
|
|
Future<String> getFamiliesToken() async {
|
|
|
try {
|
|
|
final response = await _enteDio.get("/users/families-token");
|
|
|
- if (response != null && response.statusCode == 200) {
|
|
|
+ if (response.statusCode == 200) {
|
|
|
return response.data["familiesToken"];
|
|
|
} else {
|
|
|
throw Exception("non 200 ok response");
|
|
@@ -819,6 +817,6 @@ class UserService {
|
|
|
}
|
|
|
|
|
|
bool hasEnabledTwoFactor() {
|
|
|
- return _preferences.getBool(keyHasEnabledTwoFactor);
|
|
|
+ return _preferences.getBool(keyHasEnabledTwoFactor) ?? false;
|
|
|
}
|
|
|
}
|