diff --git a/package.json b/package.json index ab335e5..f9d92aa 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ "optimize-css-assets-webpack-plugin": "^1.3.0", "sass-loader": "^4.1.1", "style-loader": "^0.13.1", + "timekeeper": "^1.0.0", "url-loader": "^0.5.7", "vue-loader": "^10.1.0", "vue-template-compiler": "^2.1.10", diff --git a/src/store/getters.js b/src/store/getters.js index 04b8906..8ca191c 100644 --- a/src/store/getters.js +++ b/src/store/getters.js @@ -1,6 +1,19 @@ export const passwords = state => state.passwords; + export const password = state => state.password; + export const isAuthenticated = state => state.authenticated; + export const isGuest = state => !state.authenticated; + export const passwordStatus = state => state.passwordStatus; + export const version = state => state.version; + +export const getCurrentPassword = state => { + const tenMinutesAgo = new Date().getTime() - 10 * 60 * 1000; + if (state.lastUse < tenMinutesAgo) { + return Object.assign({}, state.defaultPassword); + } + return Object.assign({}, state.defaultPassword, state.currentPassword); +}; diff --git a/src/store/index.js b/src/store/index.js index 38495fe..e253daa 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -9,7 +9,9 @@ Vue.use(Vuex); const state = { currentPassword: null, passwords: {}, - defaultOptions: { + defaultPassword: { + login: '', + site: '', uppercase: true, lowercase: true, numbers: true, @@ -18,6 +20,7 @@ const state = { counter: 1, version: 2 }, + lastUse: new Date().getTime(), baseURL: 'https://lesspass.com', }; diff --git a/src/store/mutation-types.js b/src/store/mutation-types.js index cbc3825..c2e09e3 100644 --- a/src/store/mutation-types.js +++ b/src/store/mutation-types.js @@ -1,4 +1,4 @@ export const LOGOUT = 'LOGOUT'; export const LOGIN = 'LOGIN'; export const SET_CURRENT_PASSWORD = 'SET_CURRENT_PASSWORD'; -export const SET_DEFAULT_OPTIONS = 'SET_DEFAULT_OPTIONS'; \ No newline at end of file +export const SET_DEFAULT_PASSWORD = 'SET_DEFAULT_PASSWORD'; \ No newline at end of file diff --git a/src/store/mutations.js b/src/store/mutations.js index 3ee537c..a6e3ee7 100644 --- a/src/store/mutations.js +++ b/src/store/mutations.js @@ -5,7 +5,7 @@ function setState(state, id, object) { set(state, id, Object.assign({}, object)); } -export default { +export const mutations = { [types.LOGIN](state){ state.authenticated = true; }, @@ -15,7 +15,7 @@ export default { [types.SET_CURRENT_PASSWORD](state, {password}){ setState(state, 'currentPassword', password); }, - [types.SET_DEFAULT_OPTIONS](state, {options}){ - setState(state, 'defaultOptions', options); + [types.SET_DEFAULT_PASSWORD](state, {options}){ + setState(state, 'defaultPassword', options); } }; diff --git a/test/store.js b/test/store.js index 5355ae4..88e4e7f 100644 --- a/test/store.js +++ b/test/store.js @@ -1,5 +1,9 @@ import test from 'ava'; +import timekeeper from 'timekeeper'; + import {mutations} from '../src/store/mutations'; +import * as getters from '../src/store/getters'; + test('LOGOUT', t => { const {LOGOUT} = mutations; @@ -32,10 +36,69 @@ test('SET_CURRENT_PASSWORD immutable', t => { t.is(state.currentPassword.version, 2); }); -test('SET_DEFAULT_OPTIONS', t => { - const {SET_DEFAULT_OPTIONS} = mutations; +test('SET_DEFAULT_PASSWORD', t => { + const {SET_DEFAULT_PASSWORD} = mutations; + const state = { + defaultPassword: { + site: '', + login: '', + uppercase: true, + lowercase: true, + numbers: true, + symbols: true, + length: 16, + counter: 1, + version: 2 + } + }; + SET_DEFAULT_PASSWORD(state, {options: {symbols: false, length: 30}}); + t.is(state.defaultPassword.length, 30); + t.false(state.defaultPassword.symbols); +}); + +test('store getter: get password 5 minutes after last use', t => { + var now = 1485989236; + var time = new Date(now * 1000); + timekeeper.freeze(time); + var fiveMinutesBefore = (now - 5 * 60) * 1000; + const state = { + lastUse: fiveMinutesBefore, + currentPassword: { + login: 'test@example.org', + length: 30 + }, + defaultPassword: { + site: '', + login: '', + uppercase: true, + lowercase: true, + numbers: true, + symbols: true, + length: 16, + counter: 1, + version: 2 + } + }; + const password = getters.getCurrentPassword(state); + t.is('test@example.org', password.login); + t.is(30, password.length); + timekeeper.reset(); +}); + +test('store getter: get password more than 10 minutes after last use', t => { + var now = 1485989236; + var time = new Date(now * 1000); + timekeeper.freeze(time); + var fifteenMinutesBefore = (now - 15 * 60) * 1000; const state = { - defaultOptions: { + lastUse: fifteenMinutesBefore, + currentPassword: { + login: 'test@example.org', + length: 30 + }, + defaultPassword: { + site: '', + login: '', uppercase: true, lowercase: true, numbers: true, @@ -45,7 +108,9 @@ test('SET_DEFAULT_OPTIONS', t => { version: 2 } }; - SET_DEFAULT_OPTIONS(state, {options: {symbols: false, length: 30}}); - t.is(state.defaultOptions.length, 30); - t.false(state.defaultOptions.symbols); + const password = getters.getCurrentPassword(state); + t.is('', password.login); + t.is('', password.site); + t.is(16, password.length); + timekeeper.reset(); }); \ No newline at end of file