Support token login

This commit is contained in:
Hillel Coren 2021-07-08 09:17:07 +03:00
parent eaa6ffe85d
commit e3a349c811
3 changed files with 163 additions and 116 deletions

View File

@ -37,6 +37,11 @@ class OAuthLoginRequest implements StartLoading {
final String oneTimePassword;
}
class TokenLogin {
TokenLogin(this.token);
final String token;
}
class UserLoadUrl {
UserLoadUrl({this.url});

View File

@ -6,6 +6,7 @@ import 'package:flutter/services.dart';
import 'package:invoiceninja_flutter/constants.dart';
import 'package:invoiceninja_flutter/redux/ui/pref_state.dart';
import 'package:invoiceninja_flutter/ui/app/buttons/app_text_button.dart';
import 'package:invoiceninja_flutter/ui/app/buttons/elevated_button.dart';
import 'package:invoiceninja_flutter/ui/app/dialogs/alert_dialog.dart';
import 'package:invoiceninja_flutter/ui/app/forms/app_toggle_buttons.dart';
import 'package:invoiceninja_flutter/ui/app/forms/decorated_form_field.dart';
@ -46,6 +47,7 @@ class _LoginState extends State<LoginView> {
final _urlController = TextEditingController();
final _secretController = TextEditingController();
final _oneTimePasswordController = TextEditingController();
final _tokenController = TextEditingController();
final _buttonController = RoundedLoadingButtonController();
@ -53,6 +55,7 @@ class _LoginState extends State<LoginView> {
String _loginError = '';
bool _tokenLogin = false;
bool _emailLogin = false;
bool _isSelfHosted = false;
bool _createAccount = true;
@ -110,6 +113,8 @@ class _LoginState extends State<LoginView> {
_passwordController.dispose();
_urlController.dispose();
_secretController.dispose();
_oneTimePasswordController.dispose();
_tokenController.dispose();
super.dispose();
}
@ -294,9 +299,34 @@ class _LoginState extends State<LoginView> {
onTap: () {
launch(kSiteUrl, forceSafariVC: false, forceWebView: false);
},
onLongPress: () {
if (kReleaseMode) {
return;
}
setState(() => _tokenLogin = !_tokenLogin);
},
),
),
),
if (_tokenLogin)
FormCard(
forceNarrow: calculateLayout(context) != AppLayout.mobile,
children: [
DecoratedFormField(
label: localization.token,
controller: _tokenController,
),
AppButton(
label: localization.submit.toUpperCase(),
onPressed: () {
final Completer<Null> completer = Completer<Null>();
viewModel.onTokenLoginPressed(context, completer,
token: _tokenController.text);
},
)
],
),
AnimatedOpacity(
duration: Duration(milliseconds: 500),
opacity: viewModel.authState.isAuthenticated ? 0 : 1,

View File

@ -48,6 +48,7 @@ class LoginVM {
@required this.onSignUpPressed,
@required this.onGoogleLoginPressed,
@required this.onGoogleSignUpPressed,
@required this.onTokenLoginPressed,
});
AppState state;
@ -79,6 +80,12 @@ class LoginVM {
@required String password,
}) onSignUpPressed;
final Function(
BuildContext,
Completer<Null> completer, {
@required String token,
}) onTokenLoginPressed;
final Function(BuildContext, Completer<Null> completer,
{String url, String secret, String oneTimePassword}) onGoogleLoginPressed;
final Function(BuildContext, Completer<Null> completer) onGoogleSignUpPressed;
@ -120,132 +127,137 @@ class LoginVM {
}
return LoginVM(
state: store.state,
isLoading: store.state.isLoading,
authState: store.state.authState,
onGoogleLoginPressed: (
BuildContext context,
Completer<Null> completer, {
@required String url,
@required String secret,
@required String oneTimePassword,
}) async {
try {
await GoogleOAuth.signOut();
final signedIn = await GoogleOAuth.signIn((idToken, accessToken) {
if (idToken.isEmpty || accessToken.isEmpty) {
GoogleOAuth.signOut();
completer.completeError(
AppLocalization.of(context).anErrorOccurredTryAgain);
} else {
store.dispatch(OAuthLoginRequest(
completer: completer,
idToken: idToken,
accessToken: accessToken,
url: _formatApiUrl(url),
secret: secret.trim(),
platform: getPlatform(context),
oneTimePassword: oneTimePassword,
));
completer.future.then((_) => _handleLogin(context: context));
}
});
if (!signedIn) {
state: store.state,
isLoading: store.state.isLoading,
authState: store.state.authState,
onGoogleLoginPressed: (
BuildContext context,
Completer<Null> completer, {
@required String url,
@required String secret,
@required String oneTimePassword,
}) async {
try {
await GoogleOAuth.signOut();
final signedIn = await GoogleOAuth.signIn((idToken, accessToken) {
if (idToken.isEmpty || accessToken.isEmpty) {
GoogleOAuth.signOut();
completer.completeError(
AppLocalization.of(context).anErrorOccurredTryAgain);
} else {
store.dispatch(OAuthLoginRequest(
completer: completer,
idToken: idToken,
accessToken: accessToken,
url: _formatApiUrl(url),
secret: secret.trim(),
platform: getPlatform(context),
oneTimePassword: oneTimePassword,
));
completer.future.then((_) => _handleLogin(context: context));
}
} catch (error) {
completer.completeError(error);
print('## onGoogleLoginPressed: $error');
});
if (!signedIn) {
completer.completeError(
AppLocalization.of(context).anErrorOccurredTryAgain);
}
},
onGoogleSignUpPressed:
(BuildContext context, Completer<Null> completer) async {
try {
await GoogleOAuth.signOut();
final signedIn = await GoogleOAuth.signUp((idToken, accessToken) {
if (idToken.isEmpty || accessToken.isEmpty) {
GoogleOAuth.signOut();
completer.completeError(
AppLocalization.of(context).anErrorOccurredTryAgain);
} else {
store.dispatch(OAuthSignUpRequest(
completer: completer,
idToken: idToken,
accessToken: accessToken,
));
completer.future.then(
(_) => _handleLogin(context: context, isSignUp: true));
}
});
if (!signedIn) {
} catch (error) {
completer.completeError(error);
print('## onGoogleLoginPressed: $error');
}
},
onGoogleSignUpPressed:
(BuildContext context, Completer<Null> completer) async {
try {
await GoogleOAuth.signOut();
final signedIn = await GoogleOAuth.signUp((idToken, accessToken) {
if (idToken.isEmpty || accessToken.isEmpty) {
GoogleOAuth.signOut();
completer.completeError(
AppLocalization.of(context).anErrorOccurredTryAgain);
} else {
store.dispatch(OAuthSignUpRequest(
completer: completer,
idToken: idToken,
accessToken: accessToken,
));
completer.future
.then((_) => _handleLogin(context: context, isSignUp: true));
}
} catch (error) {
completer.completeError(error);
print('## onGoogleSignUpPressed: $error');
}
},
onSignUpPressed: (
BuildContext context,
Completer<Null> completer, {
@required String email,
@required String password,
}) async {
if (store.state.isLoading) {
return;
});
if (!signedIn) {
completer.completeError(
AppLocalization.of(context).anErrorOccurredTryAgain);
}
} catch (error) {
completer.completeError(error);
print('## onGoogleSignUpPressed: $error');
}
},
onSignUpPressed: (
BuildContext context,
Completer<Null> completer, {
@required String email,
@required String password,
}) async {
if (store.state.isLoading) {
return;
}
store.dispatch(UserSignUpRequest(
completer: completer,
email: email.trim(),
password: password.trim(),
));
completer.future
.then((_) => _handleLogin(context: context, isSignUp: true));
},
onRecoverPressed: (
BuildContext context,
Completer<Null> completer, {
@required String email,
@required String url,
@required String secret,
}) async {
if (store.state.isLoading) {
return;
}
store.dispatch(UserSignUpRequest(
completer: completer,
email: email.trim(),
password: password.trim(),
));
completer.future
.then((_) => _handleLogin(context: context, isSignUp: true));
},
onRecoverPressed: (
BuildContext context,
Completer<Null> completer, {
@required String email,
@required String url,
@required String secret,
}) async {
if (store.state.isLoading) {
return;
}
store.dispatch(RecoverPasswordRequest(
completer: completer,
email: email.trim(),
url: _formatApiUrl(url),
secret: secret.trim(),
));
},
onLoginPressed: (
BuildContext context,
Completer<Null> completer, {
@required String email,
@required String password,
@required String url,
@required String secret,
@required String oneTimePassword,
}) async {
if (store.state.isLoading) {
return;
}
store.dispatch(RecoverPasswordRequest(
completer: completer,
email: email.trim(),
url: _formatApiUrl(url),
secret: secret.trim(),
));
},
onLoginPressed: (
BuildContext context,
Completer<Null> completer, {
@required String email,
@required String password,
@required String url,
@required String secret,
@required String oneTimePassword,
}) async {
if (store.state.isLoading) {
return;
}
store.dispatch(UserLoginRequest(
completer: completer,
email: email.trim(),
password: password.trim(),
url: _formatApiUrl(url),
secret: secret.trim(),
platform: getPlatform(context),
oneTimePassword: oneTimePassword.trim(),
));
completer.future.then((_) => _handleLogin(context: context));
});
store.dispatch(UserLoginRequest(
completer: completer,
email: email.trim(),
password: password.trim(),
url: _formatApiUrl(url),
secret: secret.trim(),
platform: getPlatform(context),
oneTimePassword: oneTimePassword.trim(),
));
completer.future.then((_) => _handleLogin(context: context));
},
onTokenLoginPressed: (BuildContext context, Completer<Null> completer,
{@required String token}) {
//
},
);
}
}