Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug fix/cannot login when token is deleted #950

Merged
merged 10 commits into from
Apr 5, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import 'package:data/data.dart';
import 'package:data/src/network/model/response/user_response.dart';
import 'package:dio/dio.dart';
import 'package:domain/domain.dart';
import 'package:flutter/foundation.dart';

class AuthenticationDataSourceImpl implements AuthenticationDataSource {

Expand Down Expand Up @@ -103,6 +104,11 @@ class AuthenticationDataSourceImpl implements AuthenticationDataSource {
return userRes.toUser();
}).catchError((error) {
_remoteExceptionThrower.throwRemoteException(error, handler: (DioError error) {
final errorCode = error.response?.headers.value(Constant.linShareAuthErrorCode) ?? '1';
final authErrorCode = LinShareErrorCode(int.tryParse(errorCode) ?? 1);
if(authErrorCode.value==1000){
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please dont use magic number. constant 1000 in value

throw NotAuthorizedUser();
}
throw UnknownError(error.response?.statusMessage!);
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
// 3 and <http://www.linshare.org/licenses/LinShare-License_AfferoGPL-v3.pdf> for
// the Additional Terms applicable to LinShare software.

import 'package:data/src/util/constant.dart';
import 'package:dio/dio.dart';
import 'package:domain/domain.dart';

Expand All @@ -50,18 +51,23 @@ class RetryAuthenticationInterceptors extends InterceptorsWrapper {
final requestOptions = dioError.requestOptions;
final extraInRequest = requestOptions.extra;
var retries = extraInRequest[RETRY_KEY] ?? 0;
if (_isAuthenticationError(dioError, retries)) {
var errorCode = dioError.response?.headers.value(Constant.linShareAuthErrorCode) ?? '1';
final authErrorCode = LinShareErrorCode(int.tryParse(errorCode) ?? 1);
try{
if (_isAuthenticationError(dioError, retries) && !authErrorCode.isTokenDeleted()) {
KhaledNjim marked this conversation as resolved.
Show resolved Hide resolved
retries++;

requestOptions.headers.addAll({AUTHORIZATION_KEY: _getTokenAsBearerHeader(_permanentToken?.token)});
requestOptions.extra = {RETRY_KEY: retries};

final response = await _dio.fetch(requestOptions);
return handler.resolve(response);

} else {
super.onError(dioError, handler);
return handler.reject(dioError);
}
}catch(exception){
KhaledNjim marked this conversation as resolved.
Show resolved Hide resolved
super.onError(dioError, handler);
}
}

bool _isAuthenticationError(DioError dioError, int retryCount) {
Expand Down
1 change: 1 addition & 0 deletions domain/lib/domain.dart
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,7 @@ export 'src/usecases/authentication/create_permanent_token_interactor.dart';
export 'src/usecases/authentication/create_permanent_token_oidc_interactor.dart';
export 'src/usecases/authentication/credential_view_state.dart';
export 'src/usecases/authentication/delete_permanent_token_interactor.dart';
export 'src/usecases/authentication/remove_permanent_token_interactor.dart';
export 'src/usecases/authentication/delete_token_oidc_interactor.dart';
export 'src/usecases/authentication/get_authorized_user_interactor.dart';
export 'src/usecases/authentication/get_credential_interactor.dart';
Expand Down
2 changes: 2 additions & 0 deletions domain/lib/src/errorcode/business_error_code.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,6 @@ class BusinessErrorCode {
static final workspaceLimit = LinShareErrorCode(50016);
static final nestedWorkgroupLimit = LinShareErrorCode(55508);
static final uploadRequestLimitReach = LinShareErrorCode(31416);
static final noValidTokenFound = [LinShareErrorCode(1005)];

}
2 changes: 2 additions & 0 deletions domain/lib/src/model/linshare_error_code.dart
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,6 @@ extension LinShareErrorCodeExtension on LinShareErrorCode {

bool isAuthenticateErrorUserLocked() =>
BusinessErrorCode.authenErrorUserLocked.contains(this);
bool isTokenDeleted()=>
BusinessErrorCode.noValidTokenFound.contains(this);
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,14 @@ class GetAuthorizedInteractor {
Future<Either<Failure, Success>> execute() async {
try {
final user = await authenticationRepository.getAuthorizedUser()
.onError((error, stackTrace) => authenticationRepository.getAuthorizedUserOffline());
.onError((error, stackTrace) {
if(error is NotAuthorizedUser){
throw error;
}
else{
return authenticationRepository.getAuthorizedUserOffline();
}
});
KhaledNjim marked this conversation as resolved.
Show resolved Hide resolved
final baseUrl = (await credentialRepository.getBaseUrl()).toString();
if (_needSetup2FA(user)) {
return Left(NeedSetup2FA());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// LinShare is an open source filesharing software, part of the LinPKI software
// suite, developed by Linagora.
//
// Copyright (C) 2020 LINAGORA
//
// This program is free software: you can redistribute it and/or modify it under the
// terms of the GNU Affero General Public License as published by the Free Software
// Foundation, either version 3 of the License, or (at your option) any later version,
// provided you comply with the Additional Terms applicable for LinShare software by
// Linagora pursuant to Section 7 of the GNU Affero General Public License,
// subsections (b), (c), and (e), pursuant to which you must notably (i) retain the
// display in the interface of the “LinShare™” trademark/logo, the "Libre & Free" mention,
// the words “You are using the Free and Open Source version of LinShare™, powered by
// Linagora © 2009–2020. Contribute to Linshare R&D by subscribing to an Enterprise
// offer!”. You must also retain the latter notice in all asynchronous messages such as
// e-mails sent with the Program, (ii) retain all hypertext links between LinShare and
// http://www.linshare.org, between linagora.com and Linagora, and (iii) refrain from
// infringing Linagora intellectual property rights over its trademarks and commercial
// brands. Other Additional Terms apply, see
// <http://www.linshare.org/licenses/LinShare-License_AfferoGPL-v3.pdf>
// for more details.
// This program is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
// more details.
// You should have received a copy of the GNU Affero General Public License and its
// applicable Additional Terms for LinShare along with this program. If not, see
// <http://www.gnu.org/licenses/> for the GNU Affero General Public License version
// 3 and <http://www.linshare.org/licenses/LinShare-License_AfferoGPL-v3.pdf> for
// the Additional Terms applicable to LinShare software.

import 'dart:developer' as developer;

import 'package:dartz/dartz.dart';
import 'package:domain/domain.dart';

import 'logout_view_state.dart';

class RemovePermanentTokenInteractor {
final TokenRepository tokenRepository;
final CredentialRepository credentialRepository;

RemovePermanentTokenInteractor(
this.tokenRepository,
this.credentialRepository
);

Future<Either<Failure, Success>> execute() async {
try {
Future.sync(() async {
await tokenRepository.removeToken();
developer.log('execute(): deleteToken', name: 'DeletePermanentTokenInteractor');
await credentialRepository.removeBaseUrl();
});
return Right(LogoutViewState());
} catch (exception) {
return Left(LogoutFailure(exception));
}
}
}
3 changes: 3 additions & 0 deletions lib/presentation/di/module/app_module.dart
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,9 @@ class AppModule {
getIt<AuthenticationRepository>(),
getIt<TokenRepository>(),
getIt<CredentialRepository>()));
getIt.registerFactory(() => RemovePermanentTokenInteractor(
getIt<TokenRepository>(),
getIt<CredentialRepository>()));
hoangdat marked this conversation as resolved.
Show resolved Hide resolved
getIt.registerFactory(() => LogoutOidcInteractor(
getIt<AuthenticationOIDCRepository>(),
getIt<CredentialRepository>()
Expand Down
1 change: 1 addition & 0 deletions lib/presentation/di/module/widget_module.dart
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,7 @@ class WidgetModule {
getIt<DeletePermanentTokenInteractor>(),
getIt<AppNavigation>(),
getIt<SaveAuthorizedUserInteractor>(),
getIt<RemovePermanentTokenInteractor>()
));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import 'authentication_arguments.dart';
class AuthenticationViewModel extends BaseViewModel {
final GetAuthorizedInteractor _getAuthorizedInteractor;
final DeletePermanentTokenInteractor deletePermanentTokenInteractor;
final RemovePermanentTokenInteractor _removePermanentTokenInteractor;
final SaveAuthorizedUserInteractor _saveAuthorizedUserInteractor;
final AppNavigation _appNavigation;
AuthenticationArguments? _authenticationArguments;
Expand All @@ -55,6 +56,7 @@ class AuthenticationViewModel extends BaseViewModel {
this.deletePermanentTokenInteractor,
this._appNavigation,
this._saveAuthorizedUserInteractor,
this._removePermanentTokenInteractor
) : super(store) {
_getAuthorizedUser();
}
Expand Down Expand Up @@ -91,7 +93,13 @@ class AuthenticationViewModel extends BaseViewModel {
_appNavigation.popAndPush(
RoutePaths.second_factor_authentication,
arguments: SecondFactorAuthenticationArguments(_authenticationArguments!.baseUrl));
} else {
}else if (failure is GetAuthorizedUserFailure &&
failure.exception is NotAuthorizedUser) {
store.dispatch(removeTokenAction());
_appNavigation.pushAndRemoveAll(RoutePaths.loginRoute,
);
}
else {
store.dispatch(initializeHomeView(_appNavigation, _authenticationArguments!.baseUrl));
}
}
Expand All @@ -101,7 +109,11 @@ class AuthenticationViewModel extends BaseViewModel {
await deletePermanentTokenInteractor.execute();
};
}

ThunkAction<AppState> removeTokenAction() {
return (Store<AppState> store) async {
await _removePermanentTokenInteractor.execute();
};
}
ThunkAction<AppState> _saveAuthorizedUserAction(User user) {
return (Store<AppState> store) async {
await _saveAuthorizedUserInteractor.execute(user);
Expand Down
Loading