TF-2384 Create KeychainSharingManager to manage data push notification
Signed-off-by: dab246 <tdvu@linagora.com> (cherry picked from commit f4b839642806597fd495da789d7654041cd9ef21)
This commit is contained in:
@@ -0,0 +1,38 @@
|
|||||||
|
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||||
|
import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||||
|
import 'package:model/extensions/account_id_extensions.dart';
|
||||||
|
import 'package:tmail_ui_user/features/push_notification/data/keychain/keychain_sharing_session.dart';
|
||||||
|
|
||||||
|
class KeychainSharingManager {
|
||||||
|
final FlutterSecureStorage _secureStorage;
|
||||||
|
|
||||||
|
KeychainSharingManager(this._secureStorage);
|
||||||
|
|
||||||
|
Future save(KeychainSharingSession keychainSharingSession) => _secureStorage.write(
|
||||||
|
key: keychainSharingSession.accountId.asString,
|
||||||
|
value: jsonEncode(keychainSharingSession.toJson()),
|
||||||
|
);
|
||||||
|
|
||||||
|
Future<bool> isSessionExist(AccountId accountId) =>
|
||||||
|
_secureStorage.containsKey(key: accountId.asString);
|
||||||
|
|
||||||
|
Future<KeychainSharingSession?> getSharingSession(AccountId accountId) async {
|
||||||
|
final jsonData = await _secureStorage.read(key: accountId.asString);
|
||||||
|
if (jsonData?.isNotEmpty == true) {
|
||||||
|
return KeychainSharingSession.fromJson(jsonDecode(jsonData!));
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future delete({String? accountId}) {
|
||||||
|
if (accountId != null) {
|
||||||
|
return _secureStorage.delete(key: accountId);
|
||||||
|
} else {
|
||||||
|
return _secureStorage.deleteAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:jmap_dart_client/http/converter/account_id_converter.dart';
|
||||||
|
import 'package:jmap_dart_client/http/converter/user_name_converter.dart';
|
||||||
|
import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||||
|
import 'package:jmap_dart_client/jmap/core/user_name.dart';
|
||||||
|
import 'package:json_annotation/json_annotation.dart';
|
||||||
|
import 'package:model/account/authentication_type.dart';
|
||||||
|
import 'package:model/oidc/token_oidc.dart';
|
||||||
|
|
||||||
|
part 'keychain_sharing_session.g.dart';
|
||||||
|
|
||||||
|
@UserNameConverter()
|
||||||
|
@AccountIdConverter()
|
||||||
|
@JsonSerializable(includeIfNull: false, explicitToJson: true)
|
||||||
|
class KeychainSharingSession with EquatableMixin {
|
||||||
|
AccountId accountId;
|
||||||
|
UserName userName;
|
||||||
|
AuthenticationType authenticationType;
|
||||||
|
String apiUrl;
|
||||||
|
String? emailState;
|
||||||
|
TokenOIDC? tokenOIDC;
|
||||||
|
String? basicAuth;
|
||||||
|
|
||||||
|
KeychainSharingSession({
|
||||||
|
required this.accountId,
|
||||||
|
required this.userName,
|
||||||
|
required this.authenticationType,
|
||||||
|
required this.apiUrl,
|
||||||
|
this.emailState,
|
||||||
|
this.tokenOIDC,
|
||||||
|
this.basicAuth,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory KeychainSharingSession.fromJson(Map<String, dynamic> json) => _$KeychainSharingSessionFromJson(json);
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => _$KeychainSharingSessionToJson(this);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [
|
||||||
|
accountId,
|
||||||
|
userName,
|
||||||
|
authenticationType,
|
||||||
|
apiUrl,
|
||||||
|
emailState,
|
||||||
|
tokenOIDC,
|
||||||
|
basicAuth,
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -0,0 +1,127 @@
|
|||||||
|
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:core/utils/app_logger.dart';
|
||||||
|
import 'package:dartz/dartz.dart';
|
||||||
|
import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||||
|
import 'package:jmap_dart_client/jmap/core/user_name.dart';
|
||||||
|
import 'package:model/account/personal_account.dart';
|
||||||
|
import 'package:model/oidc/token_oidc.dart';
|
||||||
|
import 'package:tmail_ui_user/features/login/data/local/authentication_info_cache_manager.dart';
|
||||||
|
import 'package:tmail_ui_user/features/login/data/local/token_oidc_cache_manager.dart';
|
||||||
|
import 'package:tmail_ui_user/features/mailbox/data/local/state_cache_manager.dart';
|
||||||
|
import 'package:tmail_ui_user/features/mailbox/data/model/state_type.dart';
|
||||||
|
import 'package:tmail_ui_user/features/push_notification/data/keychain/keychain_sharing_manager.dart';
|
||||||
|
import 'package:tmail_ui_user/features/push_notification/data/keychain/keychain_sharing_session.dart';
|
||||||
|
|
||||||
|
class IOSSharingManager {
|
||||||
|
final KeychainSharingManager _keychainSharingManager;
|
||||||
|
final StateCacheManager _stateCacheManager;
|
||||||
|
final TokenOidcCacheManager _tokenOidcCacheManager;
|
||||||
|
final AuthenticationInfoCacheManager _authenticationInfoCacheManager;
|
||||||
|
|
||||||
|
IOSSharingManager(
|
||||||
|
this._keychainSharingManager,
|
||||||
|
this._stateCacheManager,
|
||||||
|
this._tokenOidcCacheManager,
|
||||||
|
this._authenticationInfoCacheManager
|
||||||
|
);
|
||||||
|
|
||||||
|
bool _validateToSaveKeychain(PersonalAccount personalAccount) {
|
||||||
|
return personalAccount.accountId != null &&
|
||||||
|
personalAccount.userName != null &&
|
||||||
|
personalAccount.apiUrl != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<String?> _getEmailDeliveryStateFromKeychain(AccountId accountId) async {
|
||||||
|
try {
|
||||||
|
if (await _keychainSharingManager.isSessionExist(accountId)) {
|
||||||
|
final keychainSharingStored = await _keychainSharingManager.getSharingSession(accountId);
|
||||||
|
return keychainSharingStored?.emailState;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
} catch (e) {
|
||||||
|
logError('IOSSharingManager::_getEmailDeliveryStateFromKeychain: Exception: $e');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future saveKeyChainSharingSession(PersonalAccount personalAccount) async {
|
||||||
|
try {
|
||||||
|
if (!_validateToSaveKeychain(personalAccount)) {
|
||||||
|
logError('IOSSharingManager::saveKeyChainSharingSession: account is null');
|
||||||
|
return Future.value(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
Tuple2<TokenOIDC?, String?> authenticationInfo = await Future.wait(
|
||||||
|
[
|
||||||
|
_getTokenOidc(tokeHashId: personalAccount.id),
|
||||||
|
_getCredentialAuthentication()
|
||||||
|
],
|
||||||
|
eagerError: true
|
||||||
|
).then((listValue) => Tuple2(listValue[0] as TokenOIDC?, listValue[1] as String?));
|
||||||
|
|
||||||
|
final emailDeliveryState = await _getEmailDeliveryState(
|
||||||
|
accountId: personalAccount.accountId!,
|
||||||
|
userName: personalAccount.userName!
|
||||||
|
);
|
||||||
|
|
||||||
|
final keychainSharingSession = KeychainSharingSession(
|
||||||
|
accountId: personalAccount.accountId!,
|
||||||
|
userName: personalAccount.userName!,
|
||||||
|
authenticationType: personalAccount.authenticationType,
|
||||||
|
apiUrl: personalAccount.apiUrl!,
|
||||||
|
emailState: emailDeliveryState,
|
||||||
|
tokenOIDC: authenticationInfo.value1,
|
||||||
|
basicAuth: authenticationInfo.value2
|
||||||
|
);
|
||||||
|
log('IOSSharingManager::_saveKeyChainSharingSession: $keychainSharingSession');
|
||||||
|
await _keychainSharingManager.save(keychainSharingSession);
|
||||||
|
} catch (e) {
|
||||||
|
logError('IOSSharingManager::_saveKeyChainSharingSession: Exception: $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<TokenOIDC?> _getTokenOidc({required String tokeHashId}) async {
|
||||||
|
try {
|
||||||
|
final tokenOidc = await _tokenOidcCacheManager.getTokenOidc(tokeHashId);
|
||||||
|
log('IOSSharingManager::_getTokenOidc:tokenOidc: $tokenOidc');
|
||||||
|
return tokenOidc;
|
||||||
|
} catch (e) {
|
||||||
|
logError('IOSSharingManager::_getTokenOidc:Exception: $e');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<String?> _getCredentialAuthentication() async {
|
||||||
|
try {
|
||||||
|
final credentialInfo = await _authenticationInfoCacheManager.getAuthenticationInfoStored();
|
||||||
|
log('IOSSharingManager::_getCredentialAuthentication:credentialInfo: $credentialInfo');
|
||||||
|
return base64Encode(utf8.encode('${credentialInfo.username}:${credentialInfo.password}'));
|
||||||
|
} catch (e) {
|
||||||
|
logError('IOSSharingManager::_getCredentialAuthentication:Exception: $e');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<String?> _getEmailDeliveryState({
|
||||||
|
required AccountId accountId,
|
||||||
|
required UserName userName
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
String? emailDeliveryState = await _getEmailDeliveryStateFromKeychain(accountId);
|
||||||
|
if (emailDeliveryState == null || emailDeliveryState.isEmpty) {
|
||||||
|
final emailState = await _stateCacheManager.getState(
|
||||||
|
accountId,
|
||||||
|
userName,
|
||||||
|
StateType.email
|
||||||
|
);
|
||||||
|
emailDeliveryState = emailState?.value;
|
||||||
|
}
|
||||||
|
return emailDeliveryState;
|
||||||
|
} catch (e) {
|
||||||
|
logError('IOSSharingManager::_getEmailDeliveryState:Exception: $e');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user