TF-2387 Handle sign up twake workplace
This commit is contained in:
@@ -98,6 +98,18 @@
|
|||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name="com.linusu.flutter_web_auth_2.CallbackActivity"
|
||||||
|
android:exported="true">
|
||||||
|
<intent-filter android:label="flutter_web_auth_2">
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
|
<data android:scheme="twakemail.mobile"
|
||||||
|
android:host="redirect" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
|
||||||
<provider android:authorities="${applicationId}.firebaseinitprovider"
|
<provider android:authorities="${applicationId}.firebaseinitprovider"
|
||||||
android:name="com.google.firebase.provider.FirebaseInitProvider"
|
android:name="com.google.firebase.provider.FirebaseInitProvider"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
|
|||||||
@@ -30,5 +30,9 @@ abstract class AuthenticationClientBase {
|
|||||||
|
|
||||||
Future<bool> logoutOidc(TokenId tokenId, OIDCConfiguration config, OIDCDiscoveryResponse oidcRescovery);
|
Future<bool> logoutOidc(TokenId tokenId, OIDCConfiguration config, OIDCDiscoveryResponse oidcRescovery);
|
||||||
|
|
||||||
|
Future<TokenOIDC> signInTwakeWorkplace(OIDCConfiguration oidcConfiguration);
|
||||||
|
|
||||||
|
Future<TokenOIDC> signUpTwakeWorkplace(OIDCConfiguration oidcConfiguration);
|
||||||
|
|
||||||
factory AuthenticationClientBase({String? tag}) => getAuthenticationClientImplementation(tag: tag);
|
factory AuthenticationClientBase({String? tag}) => getAuthenticationClientImplementation(tag: tag);
|
||||||
}
|
}
|
||||||
+28
@@ -1,6 +1,7 @@
|
|||||||
|
|
||||||
import 'package:core/utils/app_logger.dart';
|
import 'package:core/utils/app_logger.dart';
|
||||||
import 'package:flutter_appauth/flutter_appauth.dart';
|
import 'package:flutter_appauth/flutter_appauth.dart';
|
||||||
|
import 'package:flutter_web_auth_2/flutter_web_auth_2.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:model/oidc/oidc_configuration.dart';
|
import 'package:model/oidc/oidc_configuration.dart';
|
||||||
import 'package:model/oidc/response/oidc_discovery_response.dart';
|
import 'package:model/oidc/response/oidc_discovery_response.dart';
|
||||||
@@ -9,6 +10,7 @@ import 'package:model/oidc/token_oidc.dart';
|
|||||||
import 'package:tmail_ui_user/features/login/data/extensions/authentication_token_extension.dart';
|
import 'package:tmail_ui_user/features/login/data/extensions/authentication_token_extension.dart';
|
||||||
import 'package:tmail_ui_user/features/login/data/extensions/token_response_extension.dart';
|
import 'package:tmail_ui_user/features/login/data/extensions/token_response_extension.dart';
|
||||||
import 'package:tmail_ui_user/features/login/data/network/authentication_client/authentication_client_base.dart';
|
import 'package:tmail_ui_user/features/login/data/network/authentication_client/authentication_client_base.dart';
|
||||||
|
import 'package:tmail_ui_user/features/login/data/network/config/oidc_constant.dart';
|
||||||
import 'package:tmail_ui_user/features/login/domain/exceptions/authentication_exception.dart';
|
import 'package:tmail_ui_user/features/login/domain/exceptions/authentication_exception.dart';
|
||||||
import 'package:tmail_ui_user/features/login/domain/extensions/oidc_configuration_extensions.dart';
|
import 'package:tmail_ui_user/features/login/domain/extensions/oidc_configuration_extensions.dart';
|
||||||
|
|
||||||
@@ -96,6 +98,32 @@ class AuthenticationClientMobile implements AuthenticationClientBase {
|
|||||||
Future<String> getAuthenticationInfo() {
|
Future<String> getAuthenticationInfo() {
|
||||||
return Future.value('');
|
return Future.value('');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<TokenOIDC> signInTwakeWorkplace(OIDCConfiguration oidcConfiguration) async {
|
||||||
|
final uri = await FlutterWebAuth2.authenticate(
|
||||||
|
url: oidcConfiguration.singInUrl,
|
||||||
|
callbackUrlScheme: OIDCConstant.twakeWorkplaceUrlScheme,
|
||||||
|
options: const FlutterWebAuth2Options(
|
||||||
|
intentFlags: ephemeralIntentFlags,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
log('AuthenticationClientMobile::signInTwakeWorkplace():Uri = $uri');
|
||||||
|
return TokenOIDC.fromUri(uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<TokenOIDC> signUpTwakeWorkplace(OIDCConfiguration oidcConfiguration) async {
|
||||||
|
final uri = await FlutterWebAuth2.authenticate(
|
||||||
|
url: oidcConfiguration.signUpUrl,
|
||||||
|
callbackUrlScheme: OIDCConstant.twakeWorkplaceUrlScheme,
|
||||||
|
options: const FlutterWebAuth2Options(
|
||||||
|
intentFlags: ephemeralIntentFlags,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
log('AuthenticationClientMobile::signUpTwakeWorkplace():Uri = $uri');
|
||||||
|
return TokenOIDC.fromUri(uri);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AuthenticationClientBase getAuthenticationClientImplementation({String? tag}) =>
|
AuthenticationClientBase getAuthenticationClientImplementation({String? tag}) =>
|
||||||
|
|||||||
@@ -106,6 +106,16 @@ class AuthenticationClientWeb implements AuthenticationClientBase {
|
|||||||
throw CanNotAuthenticationInfoOnWeb();
|
throw CanNotAuthenticationInfoOnWeb();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<TokenOIDC> signUpTwakeWorkplace(OIDCConfiguration oidcConfiguration) {
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<TokenOIDC> signInTwakeWorkplace(OIDCConfiguration oidcConfiguration) {
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AuthenticationClientBase getAuthenticationClientImplementation({String? tag}) =>
|
AuthenticationClientBase getAuthenticationClientImplementation({String? tag}) =>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import 'package:core/core.dart';
|
import 'package:core/utils/platform_info.dart';
|
||||||
import 'package:tmail_ui_user/main/utils/app_config.dart';
|
import 'package:tmail_ui_user/main/utils/app_config.dart';
|
||||||
|
|
||||||
class OIDCConstant {
|
class OIDCConstant {
|
||||||
@@ -6,10 +6,11 @@ class OIDCConstant {
|
|||||||
static List<String> get oidcScope => ['openid', 'profile', 'email', 'offline_access'];
|
static List<String> get oidcScope => ['openid', 'profile', 'email', 'offline_access'];
|
||||||
static const keyAuthorityOidc = 'KEY_AUTHORITY_OIDC';
|
static const keyAuthorityOidc = 'KEY_AUTHORITY_OIDC';
|
||||||
static const authResponseKey = "auth_info";
|
static const authResponseKey = "auth_info";
|
||||||
|
static const String twakeWorkplaceUrlScheme = 'twakemail.mobile';
|
||||||
|
static const String twakeWorkplaceRedirectUrl = '$twakeWorkplaceUrlScheme://redirect';
|
||||||
|
static const String appParameter = 'tmail';
|
||||||
|
static const String postRegisteredRedirectUrlPathParams = 'post_registered_redirect_url';
|
||||||
|
static const String postLoginRedirectUrlPathParams = 'post_login_redirect_url';
|
||||||
|
|
||||||
static String get clientId => PlatformInfo.isWeb ? AppConfig.webOidcClientId : mobileOidcClientId;
|
static String get clientId => PlatformInfo.isWeb ? AppConfig.webOidcClientId : mobileOidcClientId;
|
||||||
|
|
||||||
static String get saasClientId => PlatformInfo.isMobile
|
|
||||||
? mobileOidcClientId
|
|
||||||
: '';
|
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,10 @@
|
|||||||
|
|
||||||
|
import 'package:core/data/model/query/query_parameter.dart';
|
||||||
|
import 'package:core/data/network/config/service_path.dart';
|
||||||
import 'package:core/utils/platform_info.dart';
|
import 'package:core/utils/platform_info.dart';
|
||||||
import 'package:model/oidc/oidc_configuration.dart';
|
import 'package:model/oidc/oidc_configuration.dart';
|
||||||
|
import 'package:tmail_ui_user/features/login/data/extensions/service_path_extension.dart';
|
||||||
|
import 'package:tmail_ui_user/features/login/data/network/config/oidc_constant.dart';
|
||||||
import 'package:tmail_ui_user/main/utils/app_config.dart';
|
import 'package:tmail_ui_user/main/utils/app_config.dart';
|
||||||
|
|
||||||
extension OidcConfigurationExtensions on OIDCConfiguration {
|
extension OidcConfigurationExtensions on OIDCConfiguration {
|
||||||
@@ -28,4 +32,24 @@ extension OidcConfigurationExtensions on OIDCConfiguration {
|
|||||||
return redirectOidcMobile;
|
return redirectOidcMobile;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String get singInUrl => ServicePath(authority)
|
||||||
|
.withQueryParameters([
|
||||||
|
StringQueryParameter(
|
||||||
|
OIDCConstant.postLoginRedirectUrlPathParams,
|
||||||
|
OIDCConstant.twakeWorkplaceRedirectUrl,
|
||||||
|
),
|
||||||
|
StringQueryParameter('app', OIDCConstant.appParameter),
|
||||||
|
])
|
||||||
|
.generateEndpointPath();
|
||||||
|
|
||||||
|
String get signUpUrl => ServicePath(authority)
|
||||||
|
.withQueryParameters([
|
||||||
|
StringQueryParameter(
|
||||||
|
OIDCConstant.postRegisteredRedirectUrlPathParams,
|
||||||
|
OIDCConstant.twakeWorkplaceRedirectUrl,
|
||||||
|
),
|
||||||
|
StringQueryParameter('app', OIDCConstant.appParameter),
|
||||||
|
])
|
||||||
|
.generateEndpointPath();
|
||||||
}
|
}
|
||||||
@@ -3,5 +3,7 @@ import 'package:model/oidc/oidc_configuration.dart';
|
|||||||
import 'package:model/oidc/token_oidc.dart';
|
import 'package:model/oidc/token_oidc.dart';
|
||||||
|
|
||||||
abstract class SaasAuthenticationDataSource {
|
abstract class SaasAuthenticationDataSource {
|
||||||
Future<TokenOIDC> signIn(OIDCConfiguration oidcConfiguration);
|
Future<TokenOIDC> signInTwakeWorkplace(OIDCConfiguration oidcConfiguration);
|
||||||
|
|
||||||
|
Future<TokenOIDC> signUpTwakeWorkplace(OIDCConfiguration oidcConfiguration);
|
||||||
}
|
}
|
||||||
+9
-8
@@ -1,7 +1,6 @@
|
|||||||
import 'package:model/oidc/oidc_configuration.dart';
|
import 'package:model/oidc/oidc_configuration.dart';
|
||||||
import 'package:model/oidc/token_oidc.dart';
|
import 'package:model/oidc/token_oidc.dart';
|
||||||
import 'package:tmail_ui_user/features/login/data/network/authentication_client/authentication_client_base.dart';
|
import 'package:tmail_ui_user/features/login/data/network/authentication_client/authentication_client_base.dart';
|
||||||
import 'package:tmail_ui_user/features/login/domain/extensions/oidc_configuration_extensions.dart';
|
|
||||||
import 'package:tmail_ui_user/features/starting_page/data/datasource/saas_authentication_datasource.dart';
|
import 'package:tmail_ui_user/features/starting_page/data/datasource/saas_authentication_datasource.dart';
|
||||||
import 'package:tmail_ui_user/main/exceptions/exception_thrower.dart';
|
import 'package:tmail_ui_user/main/exceptions/exception_thrower.dart';
|
||||||
|
|
||||||
@@ -16,14 +15,16 @@ class SaasAuthenticationDataSourceImpl extends SaasAuthenticationDataSource {
|
|||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<TokenOIDC> signIn(OIDCConfiguration oidcConfiguration) {
|
Future<TokenOIDC> signInTwakeWorkplace(OIDCConfiguration oidcConfiguration) {
|
||||||
return Future.sync(() async {
|
return Future.sync(() async {
|
||||||
return await _authenticationClient.getTokenOIDC(
|
return await _authenticationClient.signInTwakeWorkplace(oidcConfiguration);
|
||||||
oidcConfiguration.clientId,
|
}).catchError(_exceptionThrower.throwException);
|
||||||
oidcConfiguration.redirectUrl,
|
}
|
||||||
oidcConfiguration.discoveryUrl,
|
|
||||||
oidcConfiguration.scopes,
|
@override
|
||||||
);
|
Future<TokenOIDC> signUpTwakeWorkplace(OIDCConfiguration oidcConfiguration) {
|
||||||
|
return Future.sync(() async {
|
||||||
|
return await _authenticationClient.signUpTwakeWorkplace(oidcConfiguration);
|
||||||
}).catchError(_exceptionThrower.throwException);
|
}).catchError(_exceptionThrower.throwException);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,7 +10,12 @@ class SaasAuthenticationRepositoryImpl extends SaasAuthenticationRepository {
|
|||||||
SaasAuthenticationRepositoryImpl(this._saasAuthenticationDataSource);
|
SaasAuthenticationRepositoryImpl(this._saasAuthenticationDataSource);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<TokenOIDC> signIn(OIDCConfiguration oidcConfiguration) {
|
Future<TokenOIDC> signInTwakeWorkplace(OIDCConfiguration oidcConfiguration) {
|
||||||
return _saasAuthenticationDataSource.signIn(oidcConfiguration);
|
return _saasAuthenticationDataSource.signInTwakeWorkplace(oidcConfiguration);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<TokenOIDC> signUpTwakeWorkplace(OIDCConfiguration oidcConfiguration) {
|
||||||
|
return _saasAuthenticationDataSource.signUpTwakeWorkplace(oidcConfiguration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,5 +2,7 @@ import 'package:model/oidc/oidc_configuration.dart';
|
|||||||
import 'package:model/oidc/token_oidc.dart';
|
import 'package:model/oidc/token_oidc.dart';
|
||||||
|
|
||||||
abstract class SaasAuthenticationRepository {
|
abstract class SaasAuthenticationRepository {
|
||||||
Future<TokenOIDC> signIn(OIDCConfiguration oidcConfiguration);
|
Future<TokenOIDC> signInTwakeWorkplace(OIDCConfiguration oidcConfiguration);
|
||||||
|
|
||||||
|
Future<TokenOIDC> signUpTwakeWorkplace(OIDCConfiguration oidcConfiguration);
|
||||||
}
|
}
|
||||||
+5
-5
@@ -3,19 +3,19 @@ import 'package:core/presentation/state/success.dart';
|
|||||||
import 'package:model/oidc/oidc_configuration.dart';
|
import 'package:model/oidc/oidc_configuration.dart';
|
||||||
import 'package:model/oidc/token_oidc.dart';
|
import 'package:model/oidc/token_oidc.dart';
|
||||||
|
|
||||||
class SignInSaasLoading extends LoadingState {}
|
class SignInTwakeWorkplaceLoading extends LoadingState {}
|
||||||
|
|
||||||
class SignInSaasSuccess extends Success {
|
class SignInTwakeWorkplaceSuccess extends Success {
|
||||||
final TokenOIDC tokenOIDC;
|
final TokenOIDC tokenOIDC;
|
||||||
final Uri baseUri;
|
final Uri baseUri;
|
||||||
final OIDCConfiguration oidcConfiguration;
|
final OIDCConfiguration oidcConfiguration;
|
||||||
|
|
||||||
SignInSaasSuccess(this.tokenOIDC, this.baseUri, this.oidcConfiguration);
|
SignInTwakeWorkplaceSuccess(this.tokenOIDC, this.baseUri, this.oidcConfiguration);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [tokenOIDC, baseUri, oidcConfiguration];
|
List<Object> get props => [tokenOIDC, baseUri, oidcConfiguration];
|
||||||
}
|
}
|
||||||
|
|
||||||
class SignInSaasFailure extends FeatureFailure {
|
class SignInTwakeWorkplaceFailure extends FeatureFailure {
|
||||||
SignInSaasFailure(dynamic exception) : super(exception: exception);
|
SignInTwakeWorkplaceFailure(dynamic exception) : super(exception: exception);
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import 'package:core/presentation/state/failure.dart';
|
||||||
|
import 'package:core/presentation/state/success.dart';
|
||||||
|
import 'package:model/oidc/oidc_configuration.dart';
|
||||||
|
import 'package:model/oidc/token_oidc.dart';
|
||||||
|
|
||||||
|
class SignUpTwakeWorkplaceLoading extends LoadingState {}
|
||||||
|
|
||||||
|
class SignUpTwakeWorkplaceSuccess extends Success {
|
||||||
|
final TokenOIDC tokenOIDC;
|
||||||
|
final Uri baseUri;
|
||||||
|
final OIDCConfiguration oidcConfiguration;
|
||||||
|
|
||||||
|
SignUpTwakeWorkplaceSuccess(this.tokenOIDC, this.baseUri, this.oidcConfiguration);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [tokenOIDC, baseUri, oidcConfiguration];
|
||||||
|
}
|
||||||
|
|
||||||
|
class SignUpTwakeWorkplaceFailure extends FeatureFailure {
|
||||||
|
SignUpTwakeWorkplaceFailure(dynamic exception) : super(exception: exception);
|
||||||
|
}
|
||||||
+7
-9
@@ -5,20 +5,19 @@ import 'package:model/account/authentication_type.dart';
|
|||||||
import 'package:model/account/personal_account.dart';
|
import 'package:model/account/personal_account.dart';
|
||||||
import 'package:model/oidc/oidc_configuration.dart';
|
import 'package:model/oidc/oidc_configuration.dart';
|
||||||
import 'package:model/oidc/token_oidc.dart';
|
import 'package:model/oidc/token_oidc.dart';
|
||||||
import 'package:rich_text_composer/views/commons/logger.dart';
|
|
||||||
import 'package:tmail_ui_user/features/login/domain/repository/account_repository.dart';
|
import 'package:tmail_ui_user/features/login/domain/repository/account_repository.dart';
|
||||||
import 'package:tmail_ui_user/features/login/domain/repository/authentication_oidc_repository.dart';
|
import 'package:tmail_ui_user/features/login/domain/repository/authentication_oidc_repository.dart';
|
||||||
import 'package:tmail_ui_user/features/login/domain/repository/credential_repository.dart';
|
import 'package:tmail_ui_user/features/login/domain/repository/credential_repository.dart';
|
||||||
import 'package:tmail_ui_user/features/starting_page/domain/repository/saas_authentication_repository.dart';
|
import 'package:tmail_ui_user/features/starting_page/domain/repository/saas_authentication_repository.dart';
|
||||||
import 'package:tmail_ui_user/features/starting_page/domain/state/sign_in_saas_state.dart';
|
import 'package:tmail_ui_user/features/starting_page/domain/state/sign_in_twake_workplace_state.dart';
|
||||||
|
|
||||||
class SignInSaasInteractor {
|
class SignInTwakeWorkplaceInteractor {
|
||||||
final SaasAuthenticationRepository _saasRepository;
|
final SaasAuthenticationRepository _saasRepository;
|
||||||
final AuthenticationOIDCRepository _authenticationOIDCRepository;
|
final AuthenticationOIDCRepository _authenticationOIDCRepository;
|
||||||
final AccountRepository _accountRepository;
|
final AccountRepository _accountRepository;
|
||||||
final CredentialRepository _credentialRepository;
|
final CredentialRepository _credentialRepository;
|
||||||
|
|
||||||
SignInSaasInteractor(
|
const SignInTwakeWorkplaceInteractor(
|
||||||
this._saasRepository,
|
this._saasRepository,
|
||||||
this._authenticationOIDCRepository,
|
this._authenticationOIDCRepository,
|
||||||
this._accountRepository,
|
this._accountRepository,
|
||||||
@@ -30,9 +29,9 @@ class SignInSaasInteractor {
|
|||||||
required OIDCConfiguration oidcConfiguration
|
required OIDCConfiguration oidcConfiguration
|
||||||
}) async* {
|
}) async* {
|
||||||
try {
|
try {
|
||||||
yield Right<Failure, Success>(SignInSaasLoading());
|
yield Right<Failure, Success>(SignInTwakeWorkplaceLoading());
|
||||||
|
|
||||||
final tokenOIDC = await _saasRepository.signIn(oidcConfiguration);
|
final tokenOIDC = await _saasRepository.signInTwakeWorkplace(oidcConfiguration);
|
||||||
|
|
||||||
await Future.wait([
|
await Future.wait([
|
||||||
_credentialRepository.saveBaseUrl(baseUri),
|
_credentialRepository.saveBaseUrl(baseUri),
|
||||||
@@ -48,10 +47,9 @@ class SignInSaasInteractor {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
yield Right<Failure, Success>(SignInSaasSuccess(tokenOIDC, baseUri, oidcConfiguration));
|
yield Right<Failure, Success>(SignInTwakeWorkplaceSuccess(tokenOIDC, baseUri, oidcConfiguration));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logError('SignInSaasInteractor::execute():Exception = $e');
|
yield Left<Failure, Success>(SignInTwakeWorkplaceFailure(e));
|
||||||
yield Left<Failure, Success>(SignInSaasFailure(e));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
import 'package:core/presentation/state/failure.dart';
|
||||||
|
import 'package:core/presentation/state/success.dart';
|
||||||
|
import 'package:dartz/dartz.dart';
|
||||||
|
import 'package:model/account/authentication_type.dart';
|
||||||
|
import 'package:model/account/personal_account.dart';
|
||||||
|
import 'package:model/oidc/oidc_configuration.dart';
|
||||||
|
import 'package:model/oidc/token_oidc.dart';
|
||||||
|
import 'package:tmail_ui_user/features/login/domain/repository/account_repository.dart';
|
||||||
|
import 'package:tmail_ui_user/features/login/domain/repository/authentication_oidc_repository.dart';
|
||||||
|
import 'package:tmail_ui_user/features/login/domain/repository/credential_repository.dart';
|
||||||
|
import 'package:tmail_ui_user/features/starting_page/domain/repository/saas_authentication_repository.dart';
|
||||||
|
import 'package:tmail_ui_user/features/starting_page/domain/state/sign_up_twake_workplace_state.dart';
|
||||||
|
|
||||||
|
class SignUpTwakeWorkplaceInteractor {
|
||||||
|
final SaasAuthenticationRepository _saasRepository;
|
||||||
|
final AuthenticationOIDCRepository _authenticationOIDCRepository;
|
||||||
|
final AccountRepository _accountRepository;
|
||||||
|
final CredentialRepository _credentialRepository;
|
||||||
|
|
||||||
|
const SignUpTwakeWorkplaceInteractor(
|
||||||
|
this._saasRepository,
|
||||||
|
this._authenticationOIDCRepository,
|
||||||
|
this._accountRepository,
|
||||||
|
this._credentialRepository
|
||||||
|
);
|
||||||
|
|
||||||
|
Stream<Either<Failure, Success>> execute({
|
||||||
|
required Uri baseUri,
|
||||||
|
required OIDCConfiguration oidcConfiguration
|
||||||
|
}) async* {
|
||||||
|
try {
|
||||||
|
yield Right<Failure, Success>(SignUpTwakeWorkplaceLoading());
|
||||||
|
|
||||||
|
final tokenOIDC = await _saasRepository.signUpTwakeWorkplace(oidcConfiguration);
|
||||||
|
|
||||||
|
await Future.wait([
|
||||||
|
_credentialRepository.saveBaseUrl(baseUri),
|
||||||
|
_authenticationOIDCRepository.persistTokenOIDC(tokenOIDC),
|
||||||
|
_authenticationOIDCRepository.persistAuthorityOidc(oidcConfiguration.authority),
|
||||||
|
]);
|
||||||
|
|
||||||
|
await _accountRepository.setCurrentAccount(
|
||||||
|
PersonalAccount(
|
||||||
|
tokenOIDC.tokenIdHash,
|
||||||
|
AuthenticationType.oidc,
|
||||||
|
isSelected: true
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
yield Right<Failure, Success>(SignUpTwakeWorkplaceSuccess(tokenOIDC, baseUri, oidcConfiguration));
|
||||||
|
} catch (e) {
|
||||||
|
yield Left<Failure, Success>(SignUpTwakeWorkplaceFailure(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,7 +8,8 @@ import 'package:tmail_ui_user/features/starting_page/data/datasource/saas_authen
|
|||||||
import 'package:tmail_ui_user/features/starting_page/data/datasource_impl/saas_authentication_datasource_impl.dart';
|
import 'package:tmail_ui_user/features/starting_page/data/datasource_impl/saas_authentication_datasource_impl.dart';
|
||||||
import 'package:tmail_ui_user/features/starting_page/data/repository/saas_authentication_repository_impl.dart';
|
import 'package:tmail_ui_user/features/starting_page/data/repository/saas_authentication_repository_impl.dart';
|
||||||
import 'package:tmail_ui_user/features/starting_page/domain/repository/saas_authentication_repository.dart';
|
import 'package:tmail_ui_user/features/starting_page/domain/repository/saas_authentication_repository.dart';
|
||||||
import 'package:tmail_ui_user/features/starting_page/domain/usecase/sign_in_saas_interactor.dart';
|
import 'package:tmail_ui_user/features/starting_page/domain/usecase/sign_in_twake_workplace_interactor.dart';
|
||||||
|
import 'package:tmail_ui_user/features/starting_page/domain/usecase/sign_up_twake_workplace_interactor.dart';
|
||||||
import 'package:tmail_ui_user/features/starting_page/presentation/twake_welcome/twake_welcome_controller.dart';
|
import 'package:tmail_ui_user/features/starting_page/presentation/twake_welcome/twake_welcome_controller.dart';
|
||||||
import 'package:tmail_ui_user/main/exceptions/remote_exception_thrower.dart';
|
import 'package:tmail_ui_user/main/exceptions/remote_exception_thrower.dart';
|
||||||
|
|
||||||
@@ -17,13 +18,20 @@ class TwakeWelcomeBindings extends BaseBindings {
|
|||||||
@override
|
@override
|
||||||
void bindingsController() {
|
void bindingsController() {
|
||||||
Get.lazyPut(() => TwakeWelcomeController(
|
Get.lazyPut(() => TwakeWelcomeController(
|
||||||
Get.find<SignInSaasInteractor>(),
|
Get.find<SignInTwakeWorkplaceInteractor>(),
|
||||||
|
Get.find<SignUpTwakeWorkplaceInteractor>(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void bindingsInteractor() {
|
void bindingsInteractor() {
|
||||||
Get.lazyPut(() => SignInSaasInteractor(
|
Get.lazyPut(() => SignInTwakeWorkplaceInteractor(
|
||||||
|
Get.find<SaasAuthenticationRepository>(),
|
||||||
|
Get.find<AuthenticationOIDCRepository>(),
|
||||||
|
Get.find<AccountRepository>(),
|
||||||
|
Get.find<CredentialRepository>(),
|
||||||
|
));
|
||||||
|
Get.lazyPut(() => SignUpTwakeWorkplaceInteractor(
|
||||||
Get.find<SaasAuthenticationRepository>(),
|
Get.find<SaasAuthenticationRepository>(),
|
||||||
Get.find<AuthenticationOIDCRepository>(),
|
Get.find<AuthenticationOIDCRepository>(),
|
||||||
Get.find<AccountRepository>(),
|
Get.find<AccountRepository>(),
|
||||||
|
|||||||
+75
-20
@@ -4,6 +4,7 @@ import 'package:dartz/dartz.dart';
|
|||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:jmap_dart_client/jmap/core/session/session.dart';
|
import 'package:jmap_dart_client/jmap/core/session/session.dart';
|
||||||
import 'package:model/oidc/oidc_configuration.dart';
|
import 'package:model/oidc/oidc_configuration.dart';
|
||||||
|
import 'package:model/oidc/token_oidc.dart';
|
||||||
import 'package:tip_dialog/tip_dialog.dart';
|
import 'package:tip_dialog/tip_dialog.dart';
|
||||||
import 'package:tmail_ui_user/features/base/reloadable/reloadable_controller.dart';
|
import 'package:tmail_ui_user/features/base/reloadable/reloadable_controller.dart';
|
||||||
import 'package:tmail_ui_user/features/home/domain/state/get_session_state.dart';
|
import 'package:tmail_ui_user/features/home/domain/state/get_session_state.dart';
|
||||||
@@ -11,8 +12,10 @@ import 'package:tmail_ui_user/features/login/data/network/config/oidc_constant.d
|
|||||||
import 'package:tmail_ui_user/features/login/domain/exceptions/authentication_exception.dart';
|
import 'package:tmail_ui_user/features/login/domain/exceptions/authentication_exception.dart';
|
||||||
import 'package:tmail_ui_user/features/login/presentation/login_form_type.dart';
|
import 'package:tmail_ui_user/features/login/presentation/login_form_type.dart';
|
||||||
import 'package:tmail_ui_user/features/login/presentation/model/login_arguments.dart';
|
import 'package:tmail_ui_user/features/login/presentation/model/login_arguments.dart';
|
||||||
import 'package:tmail_ui_user/features/starting_page/domain/state/sign_in_saas_state.dart';
|
import 'package:tmail_ui_user/features/starting_page/domain/state/sign_in_twake_workplace_state.dart';
|
||||||
import 'package:tmail_ui_user/features/starting_page/domain/usecase/sign_in_saas_interactor.dart';
|
import 'package:tmail_ui_user/features/starting_page/domain/state/sign_up_twake_workplace_state.dart';
|
||||||
|
import 'package:tmail_ui_user/features/starting_page/domain/usecase/sign_in_twake_workplace_interactor.dart';
|
||||||
|
import 'package:tmail_ui_user/features/starting_page/domain/usecase/sign_up_twake_workplace_interactor.dart';
|
||||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||||
import 'package:tmail_ui_user/main/routes/app_routes.dart';
|
import 'package:tmail_ui_user/main/routes/app_routes.dart';
|
||||||
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
|
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
|
||||||
@@ -22,9 +25,13 @@ import 'package:tmail_ui_user/main/utils/app_utils.dart';
|
|||||||
|
|
||||||
class TwakeWelcomeController extends ReloadableController {
|
class TwakeWelcomeController extends ReloadableController {
|
||||||
|
|
||||||
final SignInSaasInteractor _signInSaasInteractor;
|
final SignInTwakeWorkplaceInteractor _signInTwakeWorkplaceInteractor;
|
||||||
|
final SignUpTwakeWorkplaceInteractor _signUpTwakeWorkplaceInteractor;
|
||||||
|
|
||||||
TwakeWelcomeController(this._signInSaasInteractor);
|
TwakeWelcomeController(
|
||||||
|
this._signInTwakeWorkplaceInteractor,
|
||||||
|
this._signUpTwakeWorkplaceInteractor,
|
||||||
|
);
|
||||||
|
|
||||||
void handleUseCompanyServer() {
|
void handleUseCompanyServer() {
|
||||||
popAndPush(
|
popAndPush(
|
||||||
@@ -40,22 +47,47 @@ class TwakeWelcomeController extends ReloadableController {
|
|||||||
TipDialogHelper.loading(AppLocalizations.of(context).loadingPleaseWait);
|
TipDialogHelper.loading(AppLocalizations.of(context).loadingPleaseWait);
|
||||||
|
|
||||||
if (AppConfig.saasServerUrl.isEmpty) {
|
if (AppConfig.saasServerUrl.isEmpty) {
|
||||||
consumeState(Stream.value(Left(SignInSaasFailure(CanNotFoundSaasServerUrl()))));
|
consumeState(Stream.value(Left(SignInTwakeWorkplaceFailure(CanNotFoundSaasServerUrl()))));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final baseUri = Uri.tryParse(AppConfig.saasServerUrl);
|
final baseUri = Uri.tryParse(AppConfig.saasServerUrl);
|
||||||
|
|
||||||
if (baseUri == null) {
|
if (baseUri == null) {
|
||||||
consumeState(Stream.value(Left(SignInSaasFailure(SaasServerUriIsNull()))));
|
consumeState(Stream.value(Left(SignInTwakeWorkplaceFailure(SaasServerUriIsNull()))));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
consumeState(_signInSaasInteractor.execute(
|
consumeState(_signInTwakeWorkplaceInteractor.execute(
|
||||||
baseUri: baseUri,
|
baseUri: baseUri,
|
||||||
oidcConfiguration: OIDCConfiguration(
|
oidcConfiguration: OIDCConfiguration(
|
||||||
authority: AppConfig.registrationUrl,
|
authority: AppConfig.registrationUrl,
|
||||||
clientId: OIDCConstant.saasClientId,
|
clientId: OIDCConstant.clientId,
|
||||||
|
scopes: AppConfig.oidcScopes
|
||||||
|
)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
void onSignUpTwakeWorkplace(BuildContext context) {
|
||||||
|
TipDialogHelper.loading(AppLocalizations.of(context).loadingPleaseWait);
|
||||||
|
|
||||||
|
if (AppConfig.saasServerUrl.isEmpty) {
|
||||||
|
consumeState(Stream.value(Left(SignUpTwakeWorkplaceFailure(CanNotFoundSaasServerUrl()))));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final baseUri = Uri.tryParse(AppConfig.saasServerUrl);
|
||||||
|
|
||||||
|
if (baseUri == null) {
|
||||||
|
consumeState(Stream.value(Left(SignUpTwakeWorkplaceFailure(SaasServerUriIsNull()))));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
consumeState(_signUpTwakeWorkplaceInteractor.execute(
|
||||||
|
baseUri: baseUri,
|
||||||
|
oidcConfiguration: OIDCConfiguration(
|
||||||
|
authority: AppConfig.registrationUrl,
|
||||||
|
clientId: OIDCConstant.clientId,
|
||||||
scopes: AppConfig.oidcScopes
|
scopes: AppConfig.oidcScopes
|
||||||
)
|
)
|
||||||
));
|
));
|
||||||
@@ -63,8 +95,18 @@ class TwakeWelcomeController extends ReloadableController {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void handleSuccessViewState(Success success) {
|
void handleSuccessViewState(Success success) {
|
||||||
if (success is SignInSaasSuccess) {
|
if (success is SignInTwakeWorkplaceSuccess) {
|
||||||
_handleSignInSaasSuccess(success);
|
_synchronizeTokenAndGetSession(
|
||||||
|
baseUri: success.baseUri,
|
||||||
|
tokenOIDC: success.tokenOIDC,
|
||||||
|
oidcConfiguration: success.oidcConfiguration,
|
||||||
|
);
|
||||||
|
} else if (success is SignUpTwakeWorkplaceSuccess) {
|
||||||
|
_synchronizeTokenAndGetSession(
|
||||||
|
baseUri: success.baseUri,
|
||||||
|
tokenOIDC: success.tokenOIDC,
|
||||||
|
oidcConfiguration: success.oidcConfiguration,
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
super.handleSuccessViewState(success);
|
super.handleSuccessViewState(success);
|
||||||
}
|
}
|
||||||
@@ -72,8 +114,10 @@ class TwakeWelcomeController extends ReloadableController {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void handleFailureViewState(Failure failure) {
|
void handleFailureViewState(Failure failure) {
|
||||||
if (failure is SignInSaasFailure) {
|
if (failure is SignInTwakeWorkplaceFailure) {
|
||||||
_handleSignInSaasFailure(failure);
|
_handleSignInTwakeWorkplaceFailure(failure);
|
||||||
|
} else if (failure is SignUpTwakeWorkplaceFailure) {
|
||||||
|
_handleSignUpTwakeWorkplaceFailure(failure);
|
||||||
} else {
|
} else {
|
||||||
super.handleFailureViewState(failure);
|
super.handleFailureViewState(failure);
|
||||||
}
|
}
|
||||||
@@ -95,19 +139,30 @@ class TwakeWelcomeController extends ReloadableController {
|
|||||||
toastManager.showMessageFailure(failure);
|
toastManager.showMessageFailure(failure);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _handleSignInSaasSuccess(SignInSaasSuccess success) {
|
void _synchronizeTokenAndGetSession({
|
||||||
dynamicUrlInterceptors.setJmapUrl(success.baseUri.toString());
|
required Uri baseUri,
|
||||||
dynamicUrlInterceptors.changeBaseUrl(success.baseUri.toString());
|
required TokenOIDC tokenOIDC,
|
||||||
|
required OIDCConfiguration oidcConfiguration,
|
||||||
|
}) {
|
||||||
|
dynamicUrlInterceptors.setJmapUrl(baseUri.toString());
|
||||||
|
dynamicUrlInterceptors.changeBaseUrl(baseUri.toString());
|
||||||
authorizationInterceptors.setTokenAndAuthorityOidc(
|
authorizationInterceptors.setTokenAndAuthorityOidc(
|
||||||
newToken: success.tokenOIDC,
|
newToken: tokenOIDC,
|
||||||
newConfig: success.oidcConfiguration);
|
newConfig: oidcConfiguration);
|
||||||
authorizationIsolateInterceptors.setTokenAndAuthorityOidc(
|
authorizationIsolateInterceptors.setTokenAndAuthorityOidc(
|
||||||
newToken: success.tokenOIDC,
|
newToken: tokenOIDC,
|
||||||
newConfig: success.oidcConfiguration);
|
newConfig: oidcConfiguration);
|
||||||
|
|
||||||
getSessionAction();
|
getSessionAction();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _handleSignInSaasFailure(SignInSaasFailure failure) {
|
void _handleSignInTwakeWorkplaceFailure(SignInTwakeWorkplaceFailure failure) {
|
||||||
|
TipDialogHelper.dismiss();
|
||||||
|
|
||||||
|
toastManager.showMessageFailure(failure);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _handleSignUpTwakeWorkplaceFailure(SignUpTwakeWorkplaceFailure failure) {
|
||||||
TipDialogHelper.dismiss();
|
TipDialogHelper.dismiss();
|
||||||
|
|
||||||
toastManager.showMessageFailure(failure);
|
toastManager.showMessageFailure(failure);
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ class TwakeWelcomeView extends GetWidget<TwakeWelcomeController> {
|
|||||||
? AppLocalizations.of(context).signIn.capitalizeFirst ?? ''
|
? AppLocalizations.of(context).signIn.capitalizeFirst ?? ''
|
||||||
: null,
|
: null,
|
||||||
onSignInOnTap: () => controller.onClickSignIn(context),
|
onSignInOnTap: () => controller.onClickSignIn(context),
|
||||||
|
onCreateTwakeIdOnTap: () => controller.onSignUpTwakeWorkplace(context),
|
||||||
createTwakeIdTitle: AppConfig.isSaasPlatForm
|
createTwakeIdTitle: AppConfig.isSaasPlatForm
|
||||||
? AppLocalizations.of(context).createTwakeId
|
? AppLocalizations.of(context).createTwakeId
|
||||||
: null,
|
: null,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"@@last_modified": "2024-10-29T16:13:26.917296",
|
"@@last_modified": "2024-10-31T13:18:32.336494",
|
||||||
"initializing_data": "Initializing data...",
|
"initializing_data": "Initializing data...",
|
||||||
"@initializing_data": {
|
"@initializing_data": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
@@ -4042,7 +4042,7 @@
|
|||||||
"placeholders_order": [],
|
"placeholders_order": [],
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
},
|
},
|
||||||
"descriptionWelcomeTo": "The new Open Source standard for secure professional e-mail",
|
"descriptionWelcomeTo": "The new Open Source standard for\n secure professional e-mail",
|
||||||
"@descriptionWelcomeTo": {
|
"@descriptionWelcomeTo": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders_order": [],
|
"placeholders_order": [],
|
||||||
@@ -4065,5 +4065,11 @@
|
|||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders_order": [],
|
"placeholders_order": [],
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"createTwakeIdFailed": "Create Twake Id failed. Please check again.",
|
||||||
|
"@createTwakeIdFailed": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders_order": [],
|
||||||
|
"placeholders": {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4266,4 +4266,11 @@ class AppLocalizations {
|
|||||||
name: 'sigInSaasFailed',
|
name: 'sigInSaasFailed',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String get createTwakeIdFailed {
|
||||||
|
return Intl.message(
|
||||||
|
'Create Twake Id failed. Please check again.',
|
||||||
|
name: 'createTwakeIdFailed',
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,13 +2,15 @@ import 'package:core/presentation/state/failure.dart';
|
|||||||
import 'package:core/presentation/utils/app_toast.dart';
|
import 'package:core/presentation/utils/app_toast.dart';
|
||||||
import 'package:core/utils/app_logger.dart';
|
import 'package:core/utils/app_logger.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
import 'package:model/email/email_action_type.dart';
|
import 'package:model/email/email_action_type.dart';
|
||||||
import 'package:tmail_ui_user/features/email/domain/model/move_action.dart';
|
import 'package:tmail_ui_user/features/email/domain/model/move_action.dart';
|
||||||
import 'package:tmail_ui_user/features/home/data/exceptions/session_exceptions.dart';
|
import 'package:tmail_ui_user/features/home/data/exceptions/session_exceptions.dart';
|
||||||
import 'package:tmail_ui_user/features/home/domain/state/get_session_state.dart';
|
import 'package:tmail_ui_user/features/home/domain/state/get_session_state.dart';
|
||||||
import 'package:tmail_ui_user/features/login/data/network/oidc_error.dart';
|
import 'package:tmail_ui_user/features/login/data/network/oidc_error.dart';
|
||||||
import 'package:tmail_ui_user/features/login/domain/exceptions/authentication_exception.dart';
|
import 'package:tmail_ui_user/features/login/domain/exceptions/authentication_exception.dart';
|
||||||
import 'package:tmail_ui_user/features/starting_page/domain/state/sign_in_saas_state.dart';
|
import 'package:tmail_ui_user/features/starting_page/domain/state/sign_in_twake_workplace_state.dart';
|
||||||
|
import 'package:tmail_ui_user/features/starting_page/domain/state/sign_up_twake_workplace_state.dart';
|
||||||
import 'package:tmail_ui_user/features/thread/domain/state/empty_spam_folder_state.dart';
|
import 'package:tmail_ui_user/features/thread/domain/state/empty_spam_folder_state.dart';
|
||||||
import 'package:tmail_ui_user/features/thread/domain/state/move_multiple_email_to_mailbox_state.dart';
|
import 'package:tmail_ui_user/features/thread/domain/state/move_multiple_email_to_mailbox_state.dart';
|
||||||
import 'package:tmail_ui_user/main/exceptions/remote_exception.dart';
|
import 'package:tmail_ui_user/main/exceptions/remote_exception.dart';
|
||||||
@@ -65,8 +67,20 @@ class ToastManager {
|
|||||||
&& failure.emailActionType == EmailActionType.moveToSpam
|
&& failure.emailActionType == EmailActionType.moveToSpam
|
||||||
&& failure.moveAction == MoveAction.moving) {
|
&& failure.moveAction == MoveAction.moving) {
|
||||||
message = AppLocalizations.of(currentContext!).markAsSpamFailed;
|
message = AppLocalizations.of(currentContext!).markAsSpamFailed;
|
||||||
} else if (failure is SignInSaasFailure) {
|
} else if (failure is SignInTwakeWorkplaceFailure) {
|
||||||
message = AppLocalizations.of(currentContext!).sigInSaasFailed;
|
final exception = failure.exception;
|
||||||
|
if (exception is PlatformException && exception.message?.isNotEmpty == true) {
|
||||||
|
message = exception.message;
|
||||||
|
} else {
|
||||||
|
message = AppLocalizations.of(currentContext!).sigInSaasFailed;
|
||||||
|
}
|
||||||
|
} else if (failure is SignUpTwakeWorkplaceFailure) {
|
||||||
|
final exception = failure.exception;
|
||||||
|
if (exception is PlatformException && exception.message?.isNotEmpty == true) {
|
||||||
|
message = exception.message;
|
||||||
|
} else {
|
||||||
|
message = AppLocalizations.of(currentContext!).createTwakeIdFailed;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (message?.isNotEmpty == true) {
|
if (message?.isNotEmpty == true) {
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
class AccessTokenIsNullException implements Exception {}
|
||||||
|
|
||||||
|
class RefreshTokenIsNullException implements Exception {}
|
||||||
|
|
||||||
|
class TokenIdIsNullException implements Exception {}
|
||||||
|
|
||||||
|
class ExpiresTimeIsNullException implements Exception {}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
import 'package:core/utils/app_logger.dart';
|
import 'package:core/utils/app_logger.dart';
|
||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
import 'package:json_annotation/json_annotation.dart';
|
import 'package:json_annotation/json_annotation.dart';
|
||||||
|
import 'package:model/exceptions/token_oidc_exceptions.dart';
|
||||||
import 'package:model/oidc/converter/token_id_converter.dart';
|
import 'package:model/oidc/converter/token_id_converter.dart';
|
||||||
import 'package:model/oidc/token_id.dart';
|
import 'package:model/oidc/token_id.dart';
|
||||||
|
|
||||||
@@ -27,6 +28,38 @@ class TokenOIDC with EquatableMixin {
|
|||||||
|
|
||||||
Map<String, dynamic> toJson() => _$TokenOIDCToJson(this);
|
Map<String, dynamic> toJson() => _$TokenOIDCToJson(this);
|
||||||
|
|
||||||
|
factory TokenOIDC.fromUri(String uriString) {
|
||||||
|
final uri = Uri.parse(uriString);
|
||||||
|
final queryParams = uri.queryParameters;
|
||||||
|
|
||||||
|
final accessToken = queryParams['access_token'];
|
||||||
|
if (accessToken == null || accessToken.isEmpty) {
|
||||||
|
throw AccessTokenIsNullException();
|
||||||
|
}
|
||||||
|
|
||||||
|
final refreshToken = queryParams['refresh_token'];
|
||||||
|
if (refreshToken == null || refreshToken.isEmpty) {
|
||||||
|
throw RefreshTokenIsNullException();
|
||||||
|
}
|
||||||
|
|
||||||
|
final idToken = queryParams['id_token'];
|
||||||
|
if (idToken == null || idToken.isEmpty) {
|
||||||
|
throw TokenIdIsNullException();
|
||||||
|
}
|
||||||
|
|
||||||
|
final expiresIn = queryParams['expires_in'];
|
||||||
|
if (expiresIn == null || expiresIn.isEmpty) {
|
||||||
|
throw ExpiresTimeIsNullException();
|
||||||
|
}
|
||||||
|
|
||||||
|
return TokenOIDC(
|
||||||
|
accessToken,
|
||||||
|
TokenId(idToken),
|
||||||
|
refreshToken,
|
||||||
|
expiredTime: DateTime.now().add(Duration(seconds: int.parse(expiresIn))),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object?> get props => [token, tokenId, expiredTime, refreshToken];
|
List<Object?> get props => [token, tokenId, expiredTime, refreshToken];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:model/exceptions/token_oidc_exceptions.dart';
|
||||||
|
import 'package:model/oidc/token_oidc.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
group('TokenOIDC.fromUrl', () {
|
||||||
|
test('returns TokenOIDC instance on successful parsing', () {
|
||||||
|
const uriString = 'https://example.com/callback?access_token=valid_access&refresh_token=valid_refresh&id_token=valid_id&expires_in=3600';
|
||||||
|
final token = TokenOIDC.fromUri(uriString);
|
||||||
|
|
||||||
|
expect(token.token, 'valid_access');
|
||||||
|
expect(token.refreshToken, 'valid_refresh');
|
||||||
|
expect(token.tokenId.uuid, 'valid_id');
|
||||||
|
expect(token.expiredTime?.isAfter(DateTime.now()), isTrue);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('throws AccessTokenIsNullException if access_token is missing', () {
|
||||||
|
const uriString = 'https://example.com/callback?refresh_token=valid_refresh&id_token=valid_id&expires_in=3600';
|
||||||
|
|
||||||
|
expect(() => TokenOIDC.fromUri(uriString), throwsA(isA<AccessTokenIsNullException>()));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('throws RefreshTokenIsNullException if refresh_token is missing', () {
|
||||||
|
const uriString = 'https://example.com/callback?access_token=valid_access&id_token=valid_id&expires_in=3600';
|
||||||
|
|
||||||
|
expect(() => TokenOIDC.fromUri(uriString), throwsA(isA<RefreshTokenIsNullException>()));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('throws TokenIdIsNullException if id_token is missing', () {
|
||||||
|
const uriString = 'https://example.com/callback?access_token=valid_access&refresh_token=valid_refresh&expires_in=3600';
|
||||||
|
|
||||||
|
expect(() => TokenOIDC.fromUri(uriString), throwsA(isA<TokenIdIsNullException>()));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('throws ExpiresTimeIsNullException if expires_in is missing', () {
|
||||||
|
const uriString = 'https://example.com/callback?access_token=valid_access&refresh_token=valid_refresh&id_token=valid_id';
|
||||||
|
|
||||||
|
expect(() => TokenOIDC.fromUri(uriString), throwsA(isA<ExpiresTimeIsNullException>()));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('throws FormatException on invalid URL format', () {
|
||||||
|
const uriString = '::Not valid URI::';
|
||||||
|
|
||||||
|
expect(() => TokenOIDC.fromUri(uriString), throwsA(isA<FormatException>()));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1050,6 +1050,22 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.0.2"
|
version: "5.0.2"
|
||||||
|
flutter_web_auth_2:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: flutter_web_auth_2
|
||||||
|
sha256: "3ea3a0cc539ca74319f4f2f7484f62742fe5b2ff9a0fca37575426d6e6f07901"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.1.1"
|
||||||
|
flutter_web_auth_2_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: flutter_web_auth_2_platform_interface
|
||||||
|
sha256: e8669e262005a8354389ba2971f0fc1c36188481234ff50d013aaf993f30f739
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.1.0"
|
||||||
flutter_web_plugins:
|
flutter_web_plugins:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description: flutter
|
||||||
@@ -2224,6 +2240,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.1.4"
|
version: "4.1.4"
|
||||||
|
window_to_front:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: window_to_front
|
||||||
|
sha256: "7aef379752b7190c10479e12b5fd7c0b9d92adc96817d9e96c59937929512aee"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.0.3"
|
||||||
worker_manager:
|
worker_manager:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -257,6 +257,8 @@ dependencies:
|
|||||||
|
|
||||||
tip_dialog: 4.0.0
|
tip_dialog: 4.0.0
|
||||||
|
|
||||||
|
flutter_web_auth_2: 3.1.1
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
|||||||
Reference in New Issue
Block a user