TF-571 Implement AuthenticationOIDC repository with Hive

This commit is contained in:
Dat PHAM HOANG
2022-05-31 14:29:30 +07:00
committed by Dat H. Pham
parent 03777be4a8
commit 471465e1bc
8 changed files with 246 additions and 1 deletions
@@ -0,0 +1,131 @@
import 'package:hive/hive.dart';
import 'package:tmail_ui_user/features/caching/config/hive_cache_client.dart';
import 'package:tmail_ui_user/features/login/data/model/token_oidc_cache.dart';
class TokenOidcCacheClient extends HiveCacheClient<TokenOidcCache> {
@override
String get tableName => "TokenOidcCache";
@override
Future<void> clearAllData() {
return Future.sync(() async {
final boxToken = await openBox();
boxToken.clear();
}).catchError((error) {
throw error;
});
}
@override
Future<void> deleteItem(String key) {
return Future.sync(() async {
final boxToken = await openBox();
return boxToken.delete(key);
}).catchError((error) {
throw error;
});
}
@override
Future<void> deleteMultipleItem(List<String> listKey) {
return Future.sync(() async {
final boxToken = await openBox();
return boxToken.deleteAll(listKey);
}).catchError((error) {
throw error;
});
}
@override
Future<List<TokenOidcCache>> getAll() {
return Future.sync(() async {
final boxToken = await openBox();
return boxToken.values.toList();
}).catchError((error) {
throw error;
});
}
@override
Future<TokenOidcCache?> getItem(String key) {
return Future.sync(() async {
final boxToken = await openBox();
return boxToken.get(key);
}).catchError((error) {
throw error;
});
}
@override
Future<void> insertItem(String key, TokenOidcCache newObject) {
return Future.sync(() async {
final boxToken = await openBox();
boxToken.put(key, newObject);
}).catchError((error) {
throw error;
});
}
@override
Future<void> insertMultipleItem(Map<String, TokenOidcCache> mapObject) {
return Future.sync(() async {
final boxToken = await openBox();
boxToken.putAll(mapObject);
}).catchError((error) {
throw error;
});
}
@override
Future<bool> isExistItem(String key) {
return Future.sync(() async {
final boxToken = await openBox();
return boxToken.containsKey(key);
}).catchError((error) {
throw error;
});
}
@override
Future<bool> isExistTable() {
return Future.sync(() async {
return await Hive.boxExists(tableName);
}).catchError((error) {
throw error;
});
}
@override
Future<Box<TokenOidcCache>> openBox() {
return Future.sync(() async {
if (Hive.isBoxOpen(tableName)) {
return Hive.box<TokenOidcCache>(tableName);
}
return await Hive.openBox<TokenOidcCache>(tableName);
}).catchError((error) {
throw error;
});
}
@override
Future<void> updateItem(String key, TokenOidcCache newObject) {
return Future.sync(() async {
final boxToken = await openBox();
boxToken.put(key, newObject);
}).catchError((error) {
throw error;
});
}
@override
Future<void> updateMultipleItem(Map<String, TokenOidcCache> mapObject) {
return Future.sync(() async {
final boxToken = await openBox();
boxToken.putAll(mapObject);
}).catchError((error) {
throw error;
});
}
}
@@ -1,12 +1,14 @@
import 'package:model/model.dart';
import 'package:tmail_ui_user/features/login/data/datasource/authentication_oidc_datasource.dart';
import 'package:tmail_ui_user/features/login/data/local/token_oidc_cache_manager.dart';
import 'package:tmail_ui_user/features/login/data/network/oidc_http_client.dart';
class AuthenticationOIDCDataSourceImpl extends AuthenticationOIDCDataSource {
final OIDCHttpClient _oidcHttpClient;
final TokenOidcCacheManager _tokenOidcCacheManager;
AuthenticationOIDCDataSourceImpl(this._oidcHttpClient);
AuthenticationOIDCDataSourceImpl(this._oidcHttpClient, this._tokenOidcCacheManager);
@override
Future<OIDCResponse> checkOIDCIsAvailable(OIDCRequest oidcRequest) {
@@ -35,4 +37,14 @@ class AuthenticationOIDCDataSourceImpl extends AuthenticationOIDCDataSource {
throw error;
});
}
@override
Future<TokenOIDC> getStoredTokenOIDC(String tokenIdHash) async {
return _tokenOidcCacheManager.getTokenOidc(tokenIdHash);
}
@override
Future<void> persistTokenOIDC(TokenOIDC tokenOidc) async {
return _tokenOidcCacheManager.persistOneTokenOidc(tokenOidc);
}
}
@@ -0,0 +1,9 @@
import 'package:model/oidc/token_id.dart';
import 'package:model/oidc/token_oidc.dart';
import 'package:tmail_ui_user/features/login/data/model/token_oidc_cache.dart';
extension TokenOidcCacheExtension on TokenOidcCache {
TokenOIDC toTokenOidc() {
return TokenOIDC(token, TokenId(tokenId), refreshToken, expiredTime: expiredTime);
}
}
@@ -0,0 +1,8 @@
import 'package:model/oidc/token_oidc.dart';
import 'package:tmail_ui_user/features/login/data/model/token_oidc_cache.dart';
extension TokenOidcExtension on TokenOIDC {
TokenOidcCache toTokenOidcCache() {
return TokenOidcCache(token, tokenId.uuid, refreshToken, expiredTime: expiredTime);
}
}
@@ -0,0 +1,33 @@
import 'package:core/utils/app_logger.dart';
import 'package:model/oidc/token_oidc.dart';
import 'package:tmail_ui_user/features/caching/token_oidc_cache_client.dart';
import 'package:tmail_ui_user/features/login/data/extensions/token_oidc_cache_extension.dart';
import 'package:tmail_ui_user/features/login/data/extensions/token_oidc_extension.dart';
import 'package:tmail_ui_user/features/login/domain/exceptions/authentication_exception.dart';
class TokenOidcCacheManager {
final TokenOidcCacheClient _tokenOidcCacheClient;
TokenOidcCacheManager(this._tokenOidcCacheClient);
Future<TokenOIDC> getTokenOidc(String tokenIdHash) async {
final tokenCache = await _tokenOidcCacheClient.getItem(tokenIdHash);
if (tokenCache == null) {
throw NotFoundStoredTokenException();
} else {
return tokenCache.toTokenOidc();
}
}
Future<void> persistOneTokenOidc(TokenOIDC tokenOIDC) async {
log('TokenOidcCacheManager::persistOneTokenOidc(): $tokenOIDC');
final emailCacheExist = await _tokenOidcCacheClient.isExistTable();
if (emailCacheExist) {
await _tokenOidcCacheClient.clearAllData();
}
log('TokenOidcCacheManager::persistOneTokenOidc(): key: ${tokenOIDC.tokenId.uuid}');
log('TokenOidcCacheManager::persistOneTokenOidc(): key\'s hash: ${tokenOIDC.tokenId.hashCode.toString()}');
log('TokenOidcCacheManager::persistOneTokenOidc(): token: ${tokenOIDC.token}');
await _tokenOidcCacheClient.insertItem(tokenOIDC.tokenId.hashCode.toString(), tokenOIDC.toTokenOidcCache());
}
}
@@ -0,0 +1,26 @@
import 'package:equatable/equatable.dart';
import 'package:hive/hive.dart';
import 'package:tmail_ui_user/features/caching/utils/caching_constants.dart';
part 'token_oidc_cache.g.dart';
@HiveType(typeId: CachingConstants.TOKEN_OIDC_HIVE_CACHE_IDENTIFY)
class TokenOidcCache extends HiveObject with EquatableMixin {
@HiveField(0)
final String token;
@HiveField(1)
final String tokenId;
@HiveField(2)
final DateTime? expiredTime;
@HiveField(3)
final String refreshToken;
TokenOidcCache(this.token, this.tokenId, this.refreshToken, {this.expiredTime});
@override
List<Object?> get props => [token, tokenId, expiredTime, refreshToken];
}
@@ -24,4 +24,14 @@ class AuthenticationOIDCRepositoryImpl extends AuthenticationOIDCRepository {
Future<TokenOIDC> getTokenOIDC(String clientId, String redirectUrl, String discoveryUrl, List<String> scopes) {
return _oidcDataSource.getTokenOIDC(clientId, redirectUrl, discoveryUrl, scopes);
}
@override
Future<TokenOIDC> getStoredTokenOIDC(String tokenIdHash) {
return _oidcDataSource.getStoredTokenOIDC(tokenIdHash);
}
@override
Future<void> persistTokenOIDC(TokenOIDC tokenOidc) {
return _oidcDataSource.persistTokenOIDC(tokenOidc);
}
}
@@ -2,6 +2,7 @@ import 'package:equatable/equatable.dart';
abstract class AuthenticationException extends Equatable {
static const wrongCredential = 'Credential is wrong';
static const invalidBaseUrl = 'Invalid base URL';
const AuthenticationException(String message);
}
@@ -11,4 +12,19 @@ class BadCredentials extends AuthenticationException {
@override
List<Object> get props => [];
}
class NotFoundAuthenticatedAccountException implements Exception {
NotFoundAuthenticatedAccountException();
}
class NotFoundStoredTokenException implements Exception {
NotFoundStoredTokenException();
}
class InvalidBaseUrl extends AuthenticationException {
const InvalidBaseUrl() : super(AuthenticationException.invalidBaseUrl);
@override
List<Object?> get props => [];
}