Update auto-logout to recognize idle time in background (#6593)

* Fix wording of autoLogoutTimeLimitDescription

* AppStateController and update auto-logout functionality
feature/default_network_editable
Whymarrh Whitby 6 years ago committed by Dan J Miller
parent 08e8fb21dc
commit 28c4001f52
  1. 2
      app/_locales/en/messages.json
  2. 73
      app/scripts/controllers/app-state.js
  3. 12
      app/scripts/metamask-controller.js
  4. 17
      ui/app/pages/routes/index.js
  5. 14
      ui/app/store/actions.js

@ -161,7 +161,7 @@
"message": "Auto-Logout Timer (minutes)" "message": "Auto-Logout Timer (minutes)"
}, },
"autoLogoutTimeLimitDescription": { "autoLogoutTimeLimitDescription": {
"message": "Set the number of idle time in minutes before Metamask automatically log out" "message": "Set the idle time in minutes before MetaMask will automatically log out"
}, },
"available": { "available": {
"message": "Available" "message": "Available"

@ -0,0 +1,73 @@
const ObservableStore = require('obs-store')
const extend = require('xtend')
class AppStateController {
/**
* @constructor
* @param opts
*/
constructor (opts = {}) {
const {initState, onInactiveTimeout, preferencesStore} = opts
const {preferences} = preferencesStore.getState()
this.onInactiveTimeout = onInactiveTimeout || (() => {})
this.store = new ObservableStore(extend({
timeoutMinutes: 0,
}, initState))
this.timer = null
preferencesStore.subscribe(state => {
this._setInactiveTimeout(state.preferences.autoLogoutTimeLimit)
})
this._setInactiveTimeout(preferences.autoLogoutTimeLimit)
}
/**
* Sets the last active time to the current time
* @return {void}
*/
setLastActiveTime () {
this._resetTimer()
}
/**
* Sets the inactive timeout for the app
* @param {number} timeoutMinutes the inactive timeout in minutes
* @return {void}
* @private
*/
_setInactiveTimeout (timeoutMinutes) {
this.store.putState({
timeoutMinutes,
})
this._resetTimer()
}
/**
* Resets the internal inactive timer
*
* If the {@code timeoutMinutes} state is falsy (i.e., zero) then a new
* timer will not be created.
*
* @return {void}
* @private
*/
_resetTimer () {
const {timeoutMinutes} = this.store.getState()
if (this.timer) {
clearTimeout(this.timer)
}
if (!timeoutMinutes) {
return
}
this.timer = setTimeout(() => this.onInactiveTimeout(), timeoutMinutes * 60 * 1000)
}
}
module.exports = AppStateController

@ -25,6 +25,7 @@ const {setupMultiplex} = require('./lib/stream-utils.js')
const KeyringController = require('eth-keyring-controller') const KeyringController = require('eth-keyring-controller')
const NetworkController = require('./controllers/network') const NetworkController = require('./controllers/network')
const PreferencesController = require('./controllers/preferences') const PreferencesController = require('./controllers/preferences')
const AppStateController = require('./controllers/app-state')
const CurrencyController = require('./controllers/currency') const CurrencyController = require('./controllers/currency')
const ShapeShiftController = require('./controllers/shapeshift') const ShapeShiftController = require('./controllers/shapeshift')
const InfuraController = require('./controllers/infura') const InfuraController = require('./controllers/infura')
@ -101,6 +102,12 @@ module.exports = class MetamaskController extends EventEmitter {
network: this.networkController, network: this.networkController,
}) })
// app-state controller
this.appStateController = new AppStateController({
preferencesStore: this.preferencesController.store,
onInactiveTimeout: () => this.setLocked(),
})
// currency controller // currency controller
this.currencyController = new CurrencyController({ this.currencyController = new CurrencyController({
initState: initState.CurrencyController, initState: initState.CurrencyController,
@ -252,6 +259,7 @@ module.exports = class MetamaskController extends EventEmitter {
}) })
this.store.updateStructure({ this.store.updateStructure({
AppStateController: this.appStateController.store,
TransactionController: this.txController.store, TransactionController: this.txController.store,
KeyringController: this.keyringController.store, KeyringController: this.keyringController.store,
PreferencesController: this.preferencesController.store, PreferencesController: this.preferencesController.store,
@ -264,6 +272,7 @@ module.exports = class MetamaskController extends EventEmitter {
}) })
this.memStore = new ComposableObservableStore(null, { this.memStore = new ComposableObservableStore(null, {
AppStateController: this.appStateController.store,
NetworkController: this.networkController.store, NetworkController: this.networkController.store,
AccountTracker: this.accountTracker.store, AccountTracker: this.accountTracker.store,
TxController: this.txController.memStore, TxController: this.txController.memStore,
@ -462,6 +471,9 @@ module.exports = class MetamaskController extends EventEmitter {
// AddressController // AddressController
setAddressBook: this.addressBookController.set.bind(this.addressBookController), setAddressBook: this.addressBookController.set.bind(this.addressBookController),
// AppStateController
setLastActiveTime: nodeify(this.appStateController.setLastActiveTime, this.appStateController),
// KeyringController // KeyringController
setLocked: nodeify(this.setLocked, this), setLocked: nodeify(this.setLocked, this),
createNewVaultAndKeychain: nodeify(this.createNewVaultAndKeychain, this), createNewVaultAndKeychain: nodeify(this.createNewVaultAndKeychain, this),

@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
import { connect } from 'react-redux' import { connect } from 'react-redux'
import { Route, Switch, withRouter, matchPath } from 'react-router-dom' import { Route, Switch, withRouter, matchPath } from 'react-router-dom'
import { compose } from 'recompose' import { compose } from 'recompose'
import actions, {hideSidebar, hideWarning, lockMetamask} from '../../store/actions' import actions from '../../store/actions'
import log from 'loglevel' import log from 'loglevel'
import IdleTimer from 'react-idle-timer' import IdleTimer from 'react-idle-timer'
import {getMetaMaskAccounts, getNetworkIdentifier, preferencesSelector} from '../../selectors/selectors' import {getMetaMaskAccounts, getNetworkIdentifier, preferencesSelector} from '../../selectors/selectors'
@ -99,7 +99,7 @@ class Routes extends Component {
} }
renderRoutes () { renderRoutes () {
const { autoLogoutTimeLimit, lockMetamask } = this.props const { autoLogoutTimeLimit, setLastActiveTime } = this.props
const routes = ( const routes = (
<Switch> <Switch>
@ -122,10 +122,7 @@ class Routes extends Component {
if (autoLogoutTimeLimit > 0) { if (autoLogoutTimeLimit > 0) {
return ( return (
<IdleTimer <IdleTimer onAction={setLastActiveTime} throttle={1000}>
onIdle={lockMetamask}
timeout={autoLogoutTimeLimit * 1000 * 60}
>
{routes} {routes}
</IdleTimer> </IdleTimer>
) )
@ -338,7 +335,7 @@ Routes.propTypes = {
networkDropdownOpen: PropTypes.bool, networkDropdownOpen: PropTypes.bool,
showNetworkDropdown: PropTypes.func, showNetworkDropdown: PropTypes.func,
hideNetworkDropdown: PropTypes.func, hideNetworkDropdown: PropTypes.func,
lockMetamask: PropTypes.func, setLastActiveTime: PropTypes.func,
history: PropTypes.object, history: PropTypes.object,
location: PropTypes.object, location: PropTypes.object,
dispatch: PropTypes.func, dispatch: PropTypes.func,
@ -447,11 +444,7 @@ function mapDispatchToProps (dispatch) {
setCurrentCurrencyToUSD: () => dispatch(actions.setCurrentCurrency('usd')), setCurrentCurrencyToUSD: () => dispatch(actions.setCurrentCurrency('usd')),
toggleAccountMenu: () => dispatch(actions.toggleAccountMenu()), toggleAccountMenu: () => dispatch(actions.toggleAccountMenu()),
setMouseUserState: (isMouseUser) => dispatch(actions.setMouseUserState(isMouseUser)), setMouseUserState: (isMouseUser) => dispatch(actions.setMouseUserState(isMouseUser)),
lockMetamask: () => { setLastActiveTime: () => dispatch(actions.setLastActiveTime()),
dispatch(lockMetamask())
dispatch(hideWarning())
dispatch(hideSidebar())
},
} }
} }

@ -356,6 +356,10 @@ var actions = {
setSelectedSettingsRpcUrl, setSelectedSettingsRpcUrl,
SET_NETWORKS_TAB_ADD_MODE: 'SET_NETWORKS_TAB_ADD_MODE', SET_NETWORKS_TAB_ADD_MODE: 'SET_NETWORKS_TAB_ADD_MODE',
setNetworksTabAddMode, setNetworksTabAddMode,
// AppStateController-related actions
SET_LAST_ACTIVE_TIME: 'SET_LAST_ACTIVE_TIME',
setLastActiveTime,
} }
module.exports = actions module.exports = actions
@ -2760,3 +2764,13 @@ function setNetworksTabAddMode (isInAddMode) {
value: isInAddMode, value: isInAddMode,
} }
} }
function setLastActiveTime () {
return (dispatch) => {
background.setLastActiveTime((err) => {
if (err) {
return dispatch(actions.displayWarning(err.message))
}
})
}
}

Loading…
Cancel
Save