diff options
| -rw-r--r-- | app/app.js | 2 | ||||
| -rw-r--r-- | app/components/Account.js | 2 | ||||
| -rw-r--r-- | app/lib/backend-redux-actions.js | 15 | ||||
| -rw-r--r-- | app/lib/backend.js | 24 | ||||
| -rw-r--r-- | app/reducers/user.js | 1 | ||||
| -rw-r--r-- | package.json | 1 | ||||
| -rw-r--r-- | test/actions.spec.js | 30 |
7 files changed, 48 insertions, 27 deletions
diff --git a/app/app.js b/app/app.js index 7c358dcbda..7c69648423 100644 --- a/app/app.js +++ b/app/app.js @@ -23,7 +23,7 @@ const backend = new Backend(); // reset login state if user quit the app during login if([LoginState.connecting, LoginState.failed].includes(store.getState().user.status)) { store.dispatch(userActions.loginChange({ - status: LoginState.none + status: LoginState.none })); } diff --git a/app/components/Account.js b/app/components/Account.js index e724d314c5..1e98a425d6 100644 --- a/app/components/Account.js +++ b/app/components/Account.js @@ -2,7 +2,6 @@ import React, { Component, PropTypes } from 'react'; import { If, Then } from 'react-if'; import { Layout, Container, Header } from './Layout'; import { formatAccount } from '../lib/formatters'; -import { LoginState } from '../enums'; export default class Account extends Component { @@ -25,7 +24,6 @@ export default class Account extends Component { } render() { - const isLoggedIn = this.props.user.status === LoginState.ok; let formattedAccountId = formatAccount(this.props.user.account); return ( diff --git a/app/lib/backend-redux-actions.js b/app/lib/backend-redux-actions.js index 5718278dde..3fff1e1127 100644 --- a/app/lib/backend-redux-actions.js +++ b/app/lib/backend-redux-actions.js @@ -29,23 +29,24 @@ export default function mapBackendEventsToReduxActions(backend, store) { })); }; - const onLoggingIn = (account) => { - store.dispatch(userActions.loginChange({ + const onLoggingIn = (info) => { + store.dispatch(userActions.loginChange(Object.assign({ status: LoginState.connecting, - error: null, - account - })); + error: null + }, info))); }; - const onLogin = (account, error) => { + const onLogin = (info, error) => { const status = error ? LoginState.failed : LoginState.ok; - store.dispatch(userActions.loginChange({ status, error })); + const paidUntil = info.paidUntil ? info.paidUntil : null; + store.dispatch(userActions.loginChange({ paidUntil, status, error })); }; const onLogout = () => { store.dispatch(userActions.loginChange({ status: LoginState.none, account: null, + paidUntil: null, error: null })); }; diff --git a/app/lib/backend.js b/app/lib/backend.js index 2a608e52a1..601b0e7b64 100644 --- a/app/lib/backend.js +++ b/app/lib/backend.js @@ -1,3 +1,4 @@ +import moment from 'moment'; import Enum from './enum'; import { EventEmitter } from 'events'; import { servers } from '../config'; @@ -19,6 +20,7 @@ export default class Backend extends EventEmitter { constructor() { super(); this._account = null; + this._paidUntil = null; this._serverAddress = null; this._connStatus = ConnectionState.disconnected; this._cancellationHandler = null; @@ -30,6 +32,7 @@ export default class Backend extends EventEmitter { // Accessors get account() { return this._account; } + get paidUntil() { return this._paidUntil; } get serverAddress() { return this._serverAddress; } // Public methods @@ -66,6 +69,10 @@ export default class Backend extends EventEmitter { this._account = user.account; } + if(user.paidUntil) { + this._paidUntil = user.paidUntil; + } + this._connStatus = mapConnStatus(connect.status); } @@ -99,23 +106,34 @@ export default class Backend extends EventEmitter { login(account) { this._account = account; + this._paidUntil = null; // emit: logging in - this.emit(EventType.logging, account, null); + this.emit(EventType.logging, { account, paidUntil: this._paidUntil }, null); // @TODO: Add login call setTimeout(() => { let err = null; - if(!account.startsWith('1111')) { + let res = { account }; + + if(account.startsWith('1111')) { // accounts starting with 1111 expire in one month + res.paidUntil = moment().add(1, 'month').millisecond(0).toISOString(); + } else if(account.startsWith('2222')) { // expired in 2013 + res.paidUntil = moment('2013-01-01').toISOString(); + } else if(account.startsWith('3333')) { // expire in 2038 + res.paidUntil = moment('2038-01-01').toISOString(); + } else { err = new Error('Invalid account number.'); } + // emit: login - this.emit(EventType.login, account, err); + this.emit(EventType.login, res, err); }, 2000); } logout() { this._account = null; + this._paidUntil = null; // emit event this.emit(EventType.logout); diff --git a/app/reducers/user.js b/app/reducers/user.js index 5b89cfa991..e198ee4c26 100644 --- a/app/reducers/user.js +++ b/app/reducers/user.js @@ -4,6 +4,7 @@ import { LoginState } from '../enums'; const initialState = { account: null, + paidUntil: null, // ISO8601 status: LoginState.none, error: null }; diff --git a/package.json b/package.json index e566746203..12f701529a 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "dependencies": { "babel-runtime": "^6.22.0", "cheap-ruler": "^2.4.1", + "moment": "^2.17.1", "react": "^15.4.2", "react-custom-scrollbars": "^4.0.2", "react-dom": "^15.4.2", diff --git a/test/actions.spec.js b/test/actions.spec.js index 8b2e79e45a..0c691c2bd6 100644 --- a/test/actions.spec.js +++ b/test/actions.spec.js @@ -1,5 +1,4 @@ import { expect } from 'chai'; - import { filterIpUpdateActions, mockBackend, mockState, mockStore } from './support'; import Backend from '../app/lib/backend'; import userActions from '../app/actions/user'; @@ -12,32 +11,31 @@ describe('actions', function() { it('should login', (done) => { const expectedActions = [ - { type: 'USER_LOGIN_CHANGE', payload: { status: 'connecting', error: null, account: '111123456789' } }, - { type: 'USER_LOGIN_CHANGE', payload: { status: 'ok', error: null } } + { type: 'USER_LOGIN_CHANGE', payload: { status: 'connecting', error: null, account: '222223456789', paidUntil: null } }, + { type: 'USER_LOGIN_CHANGE', payload: { paidUntil: '2013-01-01T00:00:00.000Z', status: 'ok', error: null } } ]; - const store = mockStore(mockState()); const backend = mockBackend(store); mapBackendEventsToReduxActions(backend, store); backend.once(Backend.EventType.login, () => { const storeActions = filterIpUpdateActions(store.getActions()); - expect(storeActions).deep.equal(expectedActions); done(); }); - store.dispatch(userActions.login(backend, '111123456789')); + store.dispatch(userActions.login(backend, '222223456789')); }); - + it('should logout', (done) => { const expectedActions = [ - { type: 'USER_LOGIN_CHANGE', payload: { account: null, status: 'none', error: null } } + { type: 'USER_LOGIN_CHANGE', payload: { account: null, paidUntil: null, status: 'none', error: null } } ]; let state = Object.assign(mockState(), { user: { - account: '1111234567890', + account: '3333234567890', + paidUntil: '2038-01-01T00:00:00.000Z', status: LoginState.ok } }); @@ -64,7 +62,8 @@ describe('actions', function() { let state = Object.assign(mockState(), { user: { - account: '1111234567890', + account: '3333234567890', + paidUntil: '2038-01-01T00:00:00.000Z', status: LoginState.ok } }); @@ -91,7 +90,8 @@ describe('actions', function() { let state = Object.assign(mockState(), { user: { - account: '1111234567890', + account: '3333234567890', + paidUntil: '2038-01-01T00:00:00.000Z', status: LoginState.ok } }); @@ -117,7 +117,8 @@ describe('actions', function() { let state = Object.assign(mockState(), { user: { - account: '1111234567890', + account: '3333234567890', + paidUntil: '2038-01-01T00:00:00.000Z', status: LoginState.ok }, connect: { @@ -142,13 +143,14 @@ describe('actions', function() { it('should disconnect from VPN server on logout', (done) => { const expectedActions = [ - { type: 'USER_LOGIN_CHANGE', payload: { account: null, status: 'none', error: null } }, + { type: 'USER_LOGIN_CHANGE', payload: { account: null, paidUntil: null, status: 'none', error: null } }, { type: 'CONNECTION_CHANGE', payload: { serverAddress: null, status: 'disconnected', error: null } } ]; let state = Object.assign(mockState(), { user: { - account: '1111234567890', + account: '3333234567890', + paidUntil: '2038-01-01T00:00:00.000Z', status: LoginState.ok }, connect: { |
