Code refactor

This commit is contained in:
Hillel Coren 2021-04-29 19:03:09 +03:00
parent 79485f6c95
commit 43229f57d6
12 changed files with 94 additions and 20 deletions

View File

@ -79,6 +79,13 @@ class AuthRepository {
return sendRequest(url: url, data: credentials, secret: secret);
}
Future<dynamic> logout({@required Credentials credentials}) async {
return webClient.post(
'${credentials.url}/logout',
credentials.token,
);
}
Future<LoginResponse> oauthLogin(
{@required String idToken,
@required String accessToken,
@ -87,7 +94,6 @@ class AuthRepository {
@required String platform}) async {
final credentials = {
'id_token': idToken,
//'access_token': accessToken,
'provider': 'google',
};
url = formatApiUrl(url) + '/oauth_login';

View File

@ -236,7 +236,7 @@ Middleware<AppState> _createLoadState(
store.dispatch(RefreshData(
completer: Completer<Null>()
..future.catchError((Object error) {
store.dispatch(UserLogout(action.context));
store.dispatch(UserLogout());
})));
if (uiState.currentRoute != LoginScreen.route &&
@ -303,11 +303,11 @@ Middleware<AppState> _createLoadState(
}
}).catchError((Object error) {
print('Error (app_middleware - refresh): $error');
store.dispatch(UserLogout(action.context));
store.dispatch(UserLogout());
});
store.dispatch(RefreshData(completer: completer, clearData: true));
} else {
store.dispatch(UserLogout(action.context));
store.dispatch(UserLogout());
}
}

View File

@ -92,11 +92,18 @@ class RecoverPasswordFailure implements StopLoading {
final Object error;
}
class UserLogout implements PersistData, PersistUI {
UserLogout(this.context, {this.navigate = true});
class UserLogout implements PersistData, PersistUI {}
final BuildContext context;
final bool navigate;
class UserLogoutAll implements StartLoading {
const UserLogoutAll({this.completer});
final Completer completer;
}
class UserLogoutAllSuccess implements StopLoading {}
class UserLogoutAllFailure implements StopLoading {
const UserLogoutAllFailure(this.error);
final Object error;
}
class UserSignUpRequest implements StartLoading {

View File

@ -20,6 +20,7 @@ List<Middleware<AppState>> createStoreAuthMiddleware([
AuthRepository repository = const AuthRepository(),
]) {
final userLogout = _createUserLogout();
final userLogoutAll = _createUserLogoutAll(repository);
final loginRequest = _createLoginRequest(repository);
final oauthLoginRequest = _createOAuthLoginRequest(repository);
final signUpRequest = _createSignUpRequest(repository);
@ -33,6 +34,7 @@ List<Middleware<AppState>> createStoreAuthMiddleware([
return [
TypedMiddleware<AppState, UserLogout>(userLogout),
TypedMiddleware<AppState, UserLogoutAll>(userLogoutAll),
TypedMiddleware<AppState, UserLoginRequest>(loginRequest),
TypedMiddleware<AppState, OAuthLoginRequest>(oauthLoginRequest),
TypedMiddleware<AppState, UserSignUpRequest>(signUpRequest),
@ -57,15 +59,35 @@ Middleware<AppState> _createUserLogout() {
next(action);
if (action.navigate) {
navigatorKey.currentState.pushNamedAndRemoveUntil(
LoginScreen.route, (Route<dynamic> route) => false);
}
navigatorKey.currentState.pushNamedAndRemoveUntil(
LoginScreen.route, (Route<dynamic> route) => false);
store.dispatch(UpdateCurrentRoute(LoginScreen.route));
};
}
Middleware<AppState> _createUserLogoutAll(AuthRepository repository) {
return (Store<AppState> store, dynamic dynamicAction, NextDispatcher next) {
final action = dynamicAction as UserLogoutAll;
repository
.logout(credentials: store.state.credentials)
.then((dynamic response) {
print('## DONE MIDDLE');
store.dispatch(UserLogoutAllSuccess());
store.dispatch(UserLogout());
}).catchError((Object error) {
if (action.completer != null) {
//action.completer.completeError(error);
}
store.dispatch(UserLogoutAllFailure(error));
});
next(action);
};
}
Middleware<AppState> _createLoginRequest(AuthRepository repository) {
return (Store<AppState> store, dynamic dynamicAction, NextDispatcher next) {
final action = dynamicAction as UserLoginRequest;

View File

@ -44,7 +44,7 @@ class _DesktopSessionTimeoutState extends State<DesktopSessionTimeout> {
state.userCompanyState.lastUpdated;
if (sessionLength > sessionTimeout) {
store.dispatch(UserLogout(context));
store.dispatch(UserLogout());
} else if (sessionLength > (sessionTimeout - (1000 * 60 * 2))) {
setState(() {
_isWarned = true;

View File

@ -38,7 +38,7 @@ class ErrorDialog extends StatelessWidget {
confirmCallback(
context: context,
callback: () {
store.dispatch(UserLogout(context));
store.dispatch(UserLogout());
});
}),
TextButton(

View File

@ -73,7 +73,7 @@ class MenuDrawerVM {
message: AppLocalization.of(context).logout,
context: context,
callback: () async {
store.dispatch(UserLogout(context));
store.dispatch(UserLogout());
if (store.state.user.isConnectedToGoogle) {
GoogleOAuth.signOut();
}

View File

@ -43,10 +43,7 @@ class _MobileSessionTimeoutState extends State<MobileSessionTimeout> {
state.userCompanyState.lastUpdated;
if (sessionLength > sessionTimeout) {
store.dispatch(UserLogout(context, navigate: false));
WidgetsBinding.instance.addPostFrameCallback((duration) {
WebUtils.reloadBrowser();
});
store.dispatch(UserLogout());
}
},
);

View File

@ -70,7 +70,7 @@ class AccountManagementVM {
final context = navigatorKey.currentContext;
final state = store.state;
if (companyLength == 1) {
store.dispatch(UserLogout(context));
store.dispatch(UserLogout());
if (state.user.isConnectedToGoogle) {
GoogleOAuth.disconnect();
}

View File

@ -37,6 +37,11 @@ class _DeviceSettingsState extends State<DeviceSettings> {
final viewModel = widget.viewModel;
final state = viewModel.state;
final prefState = state.prefState;
final countSessions = state.tokenState.list
.map((tokenId) => state.tokenState.map[tokenId])
.where(
(token) => token.isSystem && token.createdUserId == state.user.id)
.length;
return Scaffold(
appBar: AppBar(
@ -247,6 +252,15 @@ class _DeviceSettingsState extends State<DeviceSettings> {
},
);
}),
ListTile(
leading: Icon(Icons.logout),
title: Text(localization.endAllSessions),
subtitle: Text(countSessions == 1
? localization.countSession
: localization.countSession
.replaceFirst(':count', '$countSessions')),
onTap: () => viewModel.onLogoutTap(context),
),
],
)
],

View File

@ -5,6 +5,7 @@ import 'package:flutter_redux/flutter_redux.dart';
import 'package:invoiceninja_flutter/constants.dart';
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
import 'package:invoiceninja_flutter/redux/auth/auth_actions.dart';
import 'package:invoiceninja_flutter/redux/dashboard/dashboard_actions.dart';
import 'package:invoiceninja_flutter/redux/ui/pref_state.dart';
import 'package:invoiceninja_flutter/ui/app/app_builder.dart';
@ -34,6 +35,7 @@ class DeviceSettingsVM {
DeviceSettingsVM({
@required this.state,
@required this.onRefreshTap,
@required this.onLogoutTap,
@required this.onDarkModeChanged,
@required this.onLayoutChanged,
@required this.onRequireAuthenticationChanged,
@ -71,6 +73,11 @@ class DeviceSettingsVM {
return DeviceSettingsVM(
state: store.state,
onRefreshTap: (BuildContext context) => _refreshData(context),
onLogoutTap: (BuildContext context) {
final completer = snackBarCompleter<Null>(
context, AppLocalization.of(context).endedAllSessions);
store.dispatch(UserLogoutAll(completer: completer));
},
onDarkModeChanged: (BuildContext context, bool value) async {
store.dispatch(UpdateUserPreferences(enableDarkMode: value));
AppBuilder.of(context).rebuild();
@ -151,6 +158,7 @@ class DeviceSettingsVM {
final AppState state;
final Function(BuildContext) onRefreshTap;
final Function(BuildContext) onLogoutTap;
final Function(BuildContext, bool) onDarkModeChanged;
final Function(BuildContext, AppLayout) onLayoutChanged;
final Function(BuildContext, AppSidebarMode) onMenuModeChanged;

View File

@ -15,6 +15,10 @@ mixin LocalizationsProvider on LocaleCodeAware {
static final Map<String, Map<String, String>> _localizedValues = {
'en': {
// STARTER: lang key - do not remove comment
'ended_all_sessions': 'Successfully ended all sessions',
'end_all_sessions': 'End All Sessions',
'count_session': '1 Session',
'count_sessions': ':count Sessions',
'invoice_created': 'Invoice Created',
'quote_created': 'Quote Created',
'credit_created': 'Credit Created',
@ -60306,6 +60310,22 @@ mixin LocalizationsProvider on LocaleCodeAware {
_localizedValues[localeCode]['credit_created'] ??
_localizedValues['en']['credit_created'];
String get endAllSessions =>
_localizedValues[localeCode]['end_all_sessions'] ??
_localizedValues['en']['end_all_sessions'];
String get countSession =>
_localizedValues[localeCode]['count_session'] ??
_localizedValues['en']['count_session'];
String get countSessions =>
_localizedValues[localeCode]['count_sessions'] ??
_localizedValues['en']['count_sessions'];
String get endedAllSessions =>
_localizedValues[localeCode]['ended_all_sessions'] ??
_localizedValues['en']['ended_all_sessions'];
String lookup(String key) {
final lookupKey = toSnakeCase(key);