TF-571 Implement AuthenticationOIDC repository with Hive
This commit is contained in:
committed by
Dat H. Pham
parent
03777be4a8
commit
471465e1bc
@@ -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:model/model.dart';
|
||||||
import 'package:tmail_ui_user/features/login/data/datasource/authentication_oidc_datasource.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';
|
import 'package:tmail_ui_user/features/login/data/network/oidc_http_client.dart';
|
||||||
|
|
||||||
class AuthenticationOIDCDataSourceImpl extends AuthenticationOIDCDataSource {
|
class AuthenticationOIDCDataSourceImpl extends AuthenticationOIDCDataSource {
|
||||||
|
|
||||||
final OIDCHttpClient _oidcHttpClient;
|
final OIDCHttpClient _oidcHttpClient;
|
||||||
|
final TokenOidcCacheManager _tokenOidcCacheManager;
|
||||||
|
|
||||||
AuthenticationOIDCDataSourceImpl(this._oidcHttpClient);
|
AuthenticationOIDCDataSourceImpl(this._oidcHttpClient, this._tokenOidcCacheManager);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<OIDCResponse> checkOIDCIsAvailable(OIDCRequest oidcRequest) {
|
Future<OIDCResponse> checkOIDCIsAvailable(OIDCRequest oidcRequest) {
|
||||||
@@ -35,4 +37,14 @@ class AuthenticationOIDCDataSourceImpl extends AuthenticationOIDCDataSource {
|
|||||||
throw error;
|
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) {
|
Future<TokenOIDC> getTokenOIDC(String clientId, String redirectUrl, String discoveryUrl, List<String> scopes) {
|
||||||
return _oidcDataSource.getTokenOIDC(clientId, redirectUrl, discoveryUrl, 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 {
|
abstract class AuthenticationException extends Equatable {
|
||||||
static const wrongCredential = 'Credential is wrong';
|
static const wrongCredential = 'Credential is wrong';
|
||||||
|
static const invalidBaseUrl = 'Invalid base URL';
|
||||||
|
|
||||||
const AuthenticationException(String message);
|
const AuthenticationException(String message);
|
||||||
}
|
}
|
||||||
@@ -12,3 +13,18 @@ class BadCredentials extends AuthenticationException {
|
|||||||
@override
|
@override
|
||||||
List<Object> get props => [];
|
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 => [];
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user