diff --git a/app/lib/rocketchat.js b/app/lib/rocketchat.js index f8330315..442bbed6 100644 --- a/app/lib/rocketchat.js +++ b/app/lib/rocketchat.js @@ -158,7 +158,7 @@ const RocketChat = { }); }, - loginWithPassword(username, password, callback) { + loginWithPassword({username, password, code}, callback) { let params = {}; const state = reduxStore.getState(); @@ -190,6 +190,15 @@ const RocketChat = { } } + if (code) { + params = { + totp: { + login: params, + code + } + }; + } + this.login(params, callback); }, @@ -415,3 +424,6 @@ Meteor.Accounts.onLogin(() => { console.log('subscriptions done.'); }); }); + +// Use for logout +// AsyncStorage.clear(); diff --git a/app/views/login.js b/app/views/login.js index 3fa97137..89ebb85f 100644 --- a/app/views/login.js +++ b/app/views/login.js @@ -1,6 +1,6 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { TextInput, StyleSheet } from 'react-native'; +import { Text, TextInput, StyleSheet } from 'react-native'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; @@ -25,6 +25,11 @@ const styles = StyleSheet.create({ padding: 5, borderWidth: 0, backgroundColor: '#f6f6f6' + }, + error: { + textAlign: 'center', + color: 'red', + paddingTop: 5 } }); @@ -67,9 +72,48 @@ export default class LoginView extends React.Component { } submit = () => { - RocketChat.loginWithPassword(this.state.username, this.state.password, () => { - this.props.navigator.dismissModal(); + this.setState({ + error: undefined }); + + const credentials = { + username: this.state.username, + password: this.state.password, + code: this.state.code + } + + RocketChat.loginWithPassword(credentials, (error) => { + if (error) { + if (error.error === 'totp-required') { + this.setState({ totp: true }); + this.codeInput.focus(); + } else { + this.setState({ + error: error.reason + }); + } + } else { + this.props.navigator.dismissModal(); + } + }); + } + + renderTOTP = () => { + if (this.state.totp) { + return ( + this.codeInput = ref} + style={styles.input} + onChangeText={code => this.setState({ code })} + keyboardType='numeric' + autoCorrect={false} + returnKeyType='done' + autoCapitalize='none' + onSubmitEditing={this.submit} + placeholder='Code' + /> + ); + } } render() { @@ -96,6 +140,8 @@ export default class LoginView extends React.Component { onSubmitEditing={this.submit} placeholder={this.props.Accounts_PasswordPlaceholder || 'Password'} /> + {this.renderTOTP()} + {this.state.error} ); } diff --git a/app/views/roomsList.js b/app/views/roomsList.js index 98f62097..dd8937fe 100644 --- a/app/views/roomsList.js +++ b/app/views/roomsList.js @@ -67,13 +67,6 @@ Meteor.Accounts.onLogin(() => { console.log('onLogin'); }); -Meteor.Accounts.onLoginFailure(() => { - Navigation.showModal({ - screen: 'Login', - animationType: 'slide-up' - }); -}); - const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 }); class RoomsListItem extends React.PureComponent { static propTypes = {