Skip to content

Commit

Permalink
timeout settings capabilities on ui
Browse files Browse the repository at this point in the history
  • Loading branch information
leordev committed Feb 9, 2018
1 parent 8523955 commit 37fca90
Show file tree
Hide file tree
Showing 11 changed files with 174 additions and 5 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -3,3 +3,4 @@ node_modules/
build/
.env
.DS_Store
*.iml
30 changes: 25 additions & 5 deletions src/background.js
Expand Up @@ -14,6 +14,7 @@ import Prompt from './models/prompts/Prompt';
import * as PromptTypes from './models/prompts/PromptTypes'
import ObjectHelpers from './util/ObjectHelpers'
import Permission from './models/Permission'
import TimingHelpers from './util/TimingHelpers';
const ecc = require('eosjs-ecc');

// Gets bound when a user logs into scatter
Expand All @@ -22,8 +23,7 @@ const ecc = require('eosjs-ecc');
let seed = '';
// let seed = '2d965eadab5c85a522ab146c4fe6871b2bf6e6ad028479dca622783bed78d7e5493a84396a339e972f916e93ab1fb5fd511e43c90007ff252eaf536973d6c48e';

const TIMEOUT_VERIFY_INTERVAL = 1 * 60000; // one minute
const TIMEOUT_INACTIVITY_INTERVAL = 15 * 60000; // fifteen minutes default
let timeoutInactivityInterval = 0;
let lastActionTimestamp = Date.now();

// This is the script that runs in the extension's background ( singleton )
Expand All @@ -50,13 +50,13 @@ export default class Background {

// Lock the user due to inactivity
timeoutLocker() {
const inactivityTime = Date.now() - lastActionTimestamp;
const inactivityTime = TimingHelpers.since(lastActionTimestamp);

if(inactivityTime > TIMEOUT_INACTIVITY_INTERVAL && seed) {
if(inactivityTime > timeoutInactivityInterval && seed) {
seed = '';
}

setTimeout(() => this.timeoutLocker(), TIMEOUT_VERIFY_INTERVAL);
setTimeout(() => this.timeoutLocker(), TimingHelpers.minutes(1));
}

/***
Expand All @@ -68,6 +68,7 @@ export default class Background {
lastActionTimestamp = Date.now();
switch(message.type){
case InternalMessageTypes.SET_SEED: Background.setSeed(sendResponse, message.payload); break;
case InternalMessageTypes.SET_TIMEOUT: Background.setTimeout(sendResponse, message.payload); break;
case InternalMessageTypes.IS_UNLOCKED: Background.isUnlocked(sendResponse); break;
case InternalMessageTypes.LOAD: Background.load(sendResponse); break;
case InternalMessageTypes.UPDATE: Background.update(sendResponse, message.payload); break;
Expand Down Expand Up @@ -97,6 +98,21 @@ export default class Background {
sendResponse(true);
}

/***
* Sets the timeout interval on scope to determine the lockout time
* @param sendResponse - Delegating response handler
* @param _timeoutMinutes - The timeout minutes to set
*/
static setTimeout(sendResponse, _timeoutMinutes){
this.load(scatter => {
timeoutInactivityInterval = TimingHelpers.minutes(_timeoutMinutes);
scatter.settings.timeoutInactivityInterval = timeoutInactivityInterval;
this.update(() => {}, scatter);
});

sendResponse(true);
}

/***
* Checks whether Scatter is locked
* @param sendResponse - Delegating response handler
Expand Down Expand Up @@ -124,6 +140,10 @@ export default class Background {
*/
static load(sendResponse){
StorageService.get().then(scatter => {

// sync the timeout inactivity interval
timeoutInactivityInterval = scatter.settings.timeoutInactivityInterval;

if(seed.length) scatter.decrypt(seed);
sendResponse(scatter)
})
Expand Down
1 change: 1 addition & 0 deletions src/components/NavbarComponent.vue
Expand Up @@ -57,6 +57,7 @@
case RouteNames.BACKUP:
case RouteNames.EXPORT_JSON: return 'Backup';
case RouteNames.DESTROY: return 'Destroy';
case RouteNames.TIMEOUT_SETTINGS: return 'Timeout Settings';
}
return 'Undefined'
},
Expand Down
1 change: 1 addition & 0 deletions src/messages/InternalMessageTypes.js
@@ -1,4 +1,5 @@
export const SET_SEED = 'setSeed';
export const SET_TIMEOUT = 'setTimeout';
export const IS_UNLOCKED = 'isUnlocked';
export const LOAD = 'load';
export const UPDATE = 'update';
Expand Down
2 changes: 2 additions & 0 deletions src/models/Settings.js
@@ -1,11 +1,13 @@
import Network from './Network';
import TimingHelpers from '../util/TimingHelpers';

export default class Settings {

constructor(){
this.networks = [];
this.backupToBlockchain = false;
this.hasEncryptionKey = false;
this.timeoutInactivityInterval = TimingHelpers.minutes(15)
}

static placeholder(){ return new Settings(); }
Expand Down
8 changes: 8 additions & 0 deletions src/store/actions.js
Expand Up @@ -22,6 +22,14 @@ export const actions = {
})
},

[Actions.SET_TIMEOUT]:({commit}, timeoutMinutes) => {
return new Promise((resolve, reject) => {
InternalMessage.payload(InternalMessageTypes.SET_TIMEOUT, timeoutMinutes).send().then(() => {
resolve(timeoutMinutes)
})
})
},

[Actions.LOAD_SCATTER]:({dispatch}) => {
return new Promise((resolve, reject) => {
InternalMessage.signal(InternalMessageTypes.LOAD).send().then(_scatter => {
Expand Down
1 change: 1 addition & 0 deletions src/store/constants.js
Expand Up @@ -7,6 +7,7 @@ export const BACKUP_SCATTER_ON_BLOCKCHAIN = 'backupScatterOnBlockchain';
export const CREATE_NEW_SCATTER = 'createNewScatter';
export const SET_MNEMONIC = 'setMnemonic';
export const SET_SEED = 'setSeed';
export const SET_TIMEOUT = 'setTimeout';
export const LOCK = 'lock';
export const DESTROY = 'destroy';

Expand Down
33 changes: 33 additions & 0 deletions src/util/TimingHelpers.js
@@ -0,0 +1,33 @@
/**
* A set of helpers for Timing operations
*/
export default class TimingHelpers {

/***
* Returns the milliseconds that has passed since the given time (unix epoch)
* @param time - past time in unix epoch format
* @returns {number} - difference from now (unix epoch)
*/
static since(time) {
return Date.now() - time;
}

/***
* Returns the milliseconds of the given minutes
* @param min - minutes, integer format
* @returns {number} - minutes in milliseconds
*/
static minutes(min) {
return min * 60000;
}

/***
* Returns the minutes based on the given milliseconds
* @param millis - milliseconds
* @returns {number} - minutes, integer
*/
static minutesFromMillis(millis) {
return millis / 60000;
}

}
1 change: 1 addition & 0 deletions src/views/SettingsView.vue
Expand Up @@ -21,6 +21,7 @@
{route:RouteNames.NETWORKS, name:'Networks', icon:'globe'},
{route:RouteNames.BACKUP, name:'Backup', icon:'save'},
{route:RouteNames.CHANGE_PASSWORD, name:'Change Password', icon:'asterisk'},
{route:RouteNames.TIMEOUT_SETTINGS, name:'Timeout Settings', icon:'clock-o'},
{route:RouteNames.DESTROY, name:'Destroy', icon:'trash-o'},
]
}}
Expand Down
97 changes: 97 additions & 0 deletions src/views/TimeoutSettingsView.vue
@@ -0,0 +1,97 @@
<template>
<section class="backup scroller">

<!-- Verified -->
<section class="panel">
<figure class="header">Timeout Minutes</figure>
<figure class="sub-header">
By changing your timeout minutes, once you validate your password in Scatter popup, your session
will be enabled and will not ask it anymore for the amount of time chosen.
</figure>
<sel :options="options" key=""
:selected="timeoutMinutes"
:parser="(obj) => obj.name"
v-on:changed="changed => bind(changed, 'timeoutMinutes')"></sel>
<btn v-on:clicked="changeTimeout" text="Change Timeout" :margined="true"></btn>
</section>

</section>
</template>

<script>
import { mapActions, mapGetters, mapState } from 'vuex'
import * as Actions from '../store/constants';
import {RouteNames} from '../vue/Routing';
import TimingHelpers from '../util/TimingHelpers';
const minutesOptions = [
{code: 1, name:'1 Minute'},
{code: 3, name:'3 Minutes'},
{code: 5, name:'5 Minutes'},
{code: 10, name:'10 Minutes'},
{code: 15, name:'15 Minutes'},
{code: 30, name:'30 Minutes'},
{code: 60, name:'1 Hour'},
{code: 120, name:'2 Hours'},
{code: 240, name:'4 Hours'},
];
export default {
data(){ return {
options: minutesOptions,
timeoutMinutes: minutesOptions.find(i => i.code ===
TimingHelpers.minutesFromMillis(this.$store.state.scatter.settings.timeoutInactivityInterval))
}},
computed: {
...mapState([
'scatter'
])
},
methods: {
bind(changed, original) { this[original] = changed },
changeTimeout(){
this[Actions.SET_TIMEOUT](this.timeoutMinutes.code).then(() => {
this.$router.push({name:RouteNames.SETTINGS});
});
},
...mapActions([
Actions.PUSH_ALERT,
Actions.SET_TIMEOUT
])
}
}
</script>

<style lang="scss">
.checkbox {
width:56px;
float:left;
margin-right:15px;
}
.backup {
font-family:'Open Sans', sans-serif;
.panel {
padding:20px;
&:not(:last-child){
border-bottom:1px solid #eaeaea;
}
.header {
color:#cecece;
font-size:11px;
padding-bottom:5px;
margin-top:-5px;
margin-bottom:10px;
border-bottom:1px solid #eaeaea;
}
.sub-header {
color:#aeaeae;
font-size:9px;
margin-bottom:20px;
}
}
}
</style>
4 changes: 4 additions & 0 deletions src/vue/Routing.js
Expand Up @@ -12,6 +12,7 @@ import DomainPermissionView from '../views/DomainPermissionView.vue'
import BackupView from '../views/BackupView.vue'
import ChangePasswordView from '../views/ChangePasswordView.vue'
import DestroyView from '../views/DestroyView.vue'
import TimeoutSettingsView from '../views/TimeoutSettingsView.vue'
import ExportJsonView from '../views/ExportJsonView.vue'
import HistoryView from '../views/HistoryView.vue'

Expand Down Expand Up @@ -41,6 +42,7 @@ export const RouteNames = {
BACKUP:'backup',
EXPORT_JSON:'exportJson',
DESTROY:'destroy',
TIMEOUT_SETTINGS:'timeoutSettings',

PROMPT_REQUEST_IDENTITY:`${promptPrefix}${PromptTypes.REQUEST_IDENTITY}`,
PROMPT_REQUEST_SIGNATURE:`${promptPrefix}${PromptTypes.REQUEST_SIGNATURE}`,
Expand All @@ -66,6 +68,7 @@ const RouteViews = {
[RouteNames.BACKUP]:BackupView,
[RouteNames.EXPORT_JSON]:ExportJsonView,
[RouteNames.DESTROY]:DestroyView,
[RouteNames.TIMEOUT_SETTINGS]:TimeoutSettingsView,

[RouteNames.PROMPT_REQUEST_IDENTITY]:RequestIdentityPrompt,
[RouteNames.PROMPT_REQUEST_SIGNATURE]:RequestSignaturePrompt,
Expand All @@ -88,6 +91,7 @@ export const RouteDepth = {
[RouteNames.NETWORKS]:101,
[RouteNames.NETWORK]:102,
[RouteNames.CHANGE_PASSWORD]:101,
[RouteNames.TIMEOUT_SETTINGS]:101,
[RouteNames.BACKUP]:101,
[RouteNames.EXPORT_JSON]:102,
[RouteNames.DESTROY]:101,
Expand Down

0 comments on commit 37fca90

Please sign in to comment.