Skip to content

Commit

Permalink
Merge pull request #1423 from LiskHQ/1337-save-selected-network
Browse files Browse the repository at this point in the history
Remember selected network - Closes #1337
  • Loading branch information
bmaggi-lisk authored Nov 7, 2018
2 parents 559bc24 + 5b9149f commit a9672cc
Show file tree
Hide file tree
Showing 11 changed files with 101 additions and 25 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ http://localhost:8080/#/?showNetwork=true
If you are actively developing in a specific route, and want to be autologged in everytime you reload the page, please add the following to localStorage:

```
localStorage.setItem('autologinUrl', 'http://localhost:4000') // desired node to log in into
localStorage.setItem('autologinKey', 'wagon stock borrow episode laundry kitten salute link globe zero feed marble') // desired account passphrase
localStorage.setItem('liskCoreUrl', 'http://localhost:4000') // desired node to log in into
localStorage.setItem('loginKey', 'wagon stock borrow episode laundry kitten salute link globe zero feed marble') // desired account passphrase
```

#### Build
Expand Down
5 changes: 5 additions & 0 deletions src/actions/peers.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { getAccount } from '../utils/api/account';
import { extractAddress, extractPublicKey } from '../utils/account';
import { accountLoggedIn, accountLoading, accountLoggedOut } from './account';
import accountConfig from '../constants/account';
import settings from '../constants/settings';

const peerSet = (data, config) => ({
data: Object.assign({
Expand Down Expand Up @@ -50,6 +51,10 @@ const login = (dispatch, getState, data, config) => {
...accountBasics,
expireTime: duration,
};
/* Save selected network to localStorage */
const networkAddress = data.network.address ? data.network.address : data.network.nodes[0];
window.localStorage.setItem(settings.keys.liskCoreUrl, networkAddress);

dispatch(accountLoggedIn(accountUpdated));
}).catch((error) => {
if (error && error.message) {
Expand Down
19 changes: 16 additions & 3 deletions src/components/login/login.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { parseSearchParams } from './../../utils/searchParams';
import Box from '../box';
// eslint-disable-next-line import/no-unresolved
import SignUp from './signUp';
import { validateUrl, addHttp } from '../../utils/login';
import { validateUrl, addHttp, getAutoLogInData, findMatchingLoginNetwork } from '../../utils/login';
import { FontIcon } from '../fontIcon';

import Ledger from '../ledger';
Expand All @@ -30,10 +30,23 @@ class Login extends React.Component {
constructor(props) {
super(props);

const { liskCoreUrl } = getAutoLogInData();

let loginNetwork = findMatchingLoginNetwork();

let address = '';

if (loginNetwork) {
loginNetwork = loginNetwork.slice(-1).shift();
} else if (!loginNetwork) {
loginNetwork = liskCoreUrl ? networks.customNode : networks.default;
address = liskCoreUrl;
}

this.state = {
passphrase: '',
address: '',
network: networks.default.code,
address,
network: loginNetwork.code,
isLedgerLogin: false,
isLedgerFirstLogin: false,
};
Expand Down
4 changes: 2 additions & 2 deletions src/constants/settings.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
const settings = {
currencies: ['USD', 'EUR'],
keys: {
autologinKey: 'autologinKey',
autologinUrl: 'autologinUrl',
loginKey: 'loginKey',
liskCoreUrl: 'liskCoreUrl',
},
};
export default settings;
6 changes: 3 additions & 3 deletions src/store/middlewares/account.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,11 +123,11 @@ const autoLogInIfNecessary = (store) => {
const autologinData = getAutoLogInData();
if (shouldAutoLogIn(autologinData)) {
store.dispatch(activePeerSet({
passphrase: autologinData[settings.keys.autologinKey],
network: { ...networks.customNode, address: autologinData[settings.keys.autologinUrl] },
passphrase: autologinData[settings.keys.loginKey],
network: { ...networks.customNode, address: autologinData[settings.keys.liskCoreUrl] },
options: {
code: networks.customNode.code,
address: autologinData[settings.keys.autologinUrl],
address: autologinData[settings.keys.liskCoreUrl],
},
}));
store.dispatch(activePeerUpdate({
Expand Down
4 changes: 2 additions & 2 deletions src/store/middlewares/account.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -209,8 +209,8 @@ describe('Account middleware', () => {

it(`should dispatch ${actionTypes.activePeerSet} action on ${actionTypes.storeCreated} if autologin data found in localStorage`, () => {
getAutoLogInDataMock.withArgs().returns({
[settings.keys.autologinKey]: passphrase,
[settings.keys.autologinUrl]: networks.testnet.nodes[0],
[settings.keys.loginKey]: passphrase,
[settings.keys.liskCoreUrl]: networks.testnet.nodes[0],
});
middleware(store)(next)(storeCreatedAction);
expect(store.dispatch).to.have.been.calledWith(activePeerMock);
Expand Down
16 changes: 14 additions & 2 deletions src/store/middlewares/peers.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,25 @@ import { activePeerSet, activePeerUpdate } from '../../actions/peers';
import actionTypes from '../../constants/actions';
import networks from './../../constants/networks';
import getNetwork from './../../utils/getNetwork';
import { shouldAutoLogIn, getAutoLogInData } from './../../utils/login';
import { shouldAutoLogIn, getAutoLogInData, findMatchingLoginNetwork } from './../../utils/login';

const peersMiddleware = store => next => (action) => {
next(action);

const network = Object.assign({}, getNetwork(networks.mainnet.code));
const autologinData = getAutoLogInData();
const { liskCoreUrl } = autologinData;

let loginNetwork = findMatchingLoginNetwork();

// if cant find login network but liskCoreUrl is set then is custom node
// else default network
if (loginNetwork) {
loginNetwork = loginNetwork.slice(-1).shift();
} else if (!loginNetwork) {
loginNetwork = liskCoreUrl ? networks.customNode : networks.default;
}

const network = Object.assign({}, getNetwork(loginNetwork.code));

switch (action.type) {
case actionTypes.storeCreated:
Expand Down
39 changes: 38 additions & 1 deletion src/store/middlewares/peers.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,21 @@ import { spy, stub } from 'sinon';
import middleware from './peers';
import actionTypes from '../../constants/actions';
import { activePeerSet } from '../../actions/peers';
import * as loginUtils from './../../utils/login';

describe('Peer middleware', () => {
let store;
let next;
let localStorageStub;
let loginUtilsStub;
let getAutoLogInDataStub;

beforeEach(() => {
next = spy();
store = stub();
localStorageStub = stub(localStorage, 'get');
loginUtilsStub = stub(loginUtils, 'findMatchingLoginNetwork');
getAutoLogInDataStub = stub(loginUtils, 'getAutoLogInData');

store.getState = () => ({
peers: {
Expand All @@ -25,11 +30,15 @@ describe('Peer middleware', () => {

afterEach(() => {
localStorageStub.restore();
loginUtilsStub.restore();
getAutoLogInDataStub.restore();
});

it('should just pass action along', () => {
localStorageStub.returns(JSON.stringify([]));

getAutoLogInDataStub.returns({
liskCoreUrl: 'https://testnet.lisk.io',
});
const sampleAction = {
type: 'SAMPLE_TYPE',
data: 'SAMPLE_DATA',
Expand All @@ -38,16 +47,44 @@ describe('Peer middleware', () => {
expect(next).to.have.been.calledWith(sampleAction);
});

it('should get the correct network', () => {
getAutoLogInDataStub.returns({
liskCoreUrl: 'https://testnet.lisk.io',
});
loginUtilsStub.returns();
const storeCreated = { type: actionTypes.storeCreated };
localStorageStub.returns(JSON.stringify([]));
middleware(store)(next)(storeCreated);
expect(store.dispatch).to.have.been.calledWith();
});

it('should auto login without shouldAutoLogIn', () => {
getAutoLogInDataStub.returns({
liskCoreUrl: undefined,
});
loginUtilsStub.returns();
const storeCreated = { type: actionTypes.storeCreated };
localStorageStub.returns(JSON.stringify([]));
middleware(store)(next)(storeCreated);
expect(store.dispatch).to.have.been.calledWith();
});

it('should dispatch activePeerSet if there are no saved accounts', () => {
const storeCreated = { type: actionTypes.storeCreated };
localStorageStub.returns(JSON.stringify([]));
getAutoLogInDataStub.returns({
liskCoreUrl: 'https://testnet.lisk.io',
});
middleware(store)(next)(storeCreated);
expect(store.dispatch).to.have.been.calledWith();
});

it('should not dispatch activePeerSet if there are saved accounts', () => {
const storeCreated = { type: actionTypes.storeCreated };
localStorageStub.returns(JSON.stringify([{}, {}]));
getAutoLogInDataStub.returns({
liskCoreUrl: 'https://testnet.lisk.io',
});
middleware(store)(next)(storeCreated);
expect(store.dispatch).to.not.have.been.calledWith(activePeerSet());
});
Expand Down
17 changes: 13 additions & 4 deletions src/utils/login.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import i18next from 'i18next';
import settings from './../constants/settings';
import networks from './../constants/networks';

// https://stackoverflow.com/questions/3809401/what-is-a-good-regular-expression-to-match-a-url
// eslint-disable-next-line no-useless-escape
Expand Down Expand Up @@ -35,10 +36,18 @@ export const validateUrl = (value) => {


export const getAutoLogInData = () => ({
[settings.keys.autologinKey]: localStorage.getItem(settings.keys.autologinKey),
[settings.keys.autologinUrl]: localStorage.getItem(settings.keys.autologinUrl),
[settings.keys.loginKey]: localStorage.getItem(settings.keys.loginKey),
[settings.keys.liskCoreUrl]: localStorage.getItem(settings.keys.liskCoreUrl),
});

export const shouldAutoLogIn = autologin =>
autologin[settings.keys.autologinUrl] && autologin[settings.keys.autologinUrl] !== '' &&
autologin[settings.keys.autologinKey] && autologin[settings.keys.autologinKey] !== '';
autologin[settings.keys.liskCoreUrl] && autologin[settings.keys.liskCoreUrl] !== '' &&
autologin[settings.keys.loginKey] && autologin[settings.keys.loginKey] !== '';

export const findMatchingLoginNetwork = () => {
const { liskCoreUrl } = getAutoLogInData();
return Object.entries(networks).find((network) => {
const { nodes } = network.slice(-1).shift();
return Array.isArray(nodes) ? nodes.includes(liskCoreUrl) : false;
});
};
8 changes: 4 additions & 4 deletions test/cypress/e2e/txDetails.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ describe('Tx details', () => {
cy.get(ss.txAmount).should('have.text', '-5');
cy.get(ss.txFee).should('have.text', '0.1');
cy.get(ss.txConfirmations).should('have.text', '');
cy.get(ss.txId).contains(/^\d{19}/);
cy.get(ss.txId).contains(/^\d{1,20}/);
cy.get(ss.txReference).should('have.text', 'test-details');
// After confirmation
cy.get(ss.txDate, { timeout: txConfirmationTimeout }).contains(new Date().getFullYear());
Expand All @@ -62,7 +62,7 @@ describe('Tx details', () => {
cy.get(ss.txRemovedVotes).should('not.exist');
cy.get(ss.txFee).should('have.text', '1');
cy.get(ss.txConfirmations).contains(/^\d/);
cy.get(ss.txId).contains(/^\d{19}/);
cy.get(ss.txId).contains(/^\d{1,20}/);
cy.get(ss.txReference).should('have.text', '-');
});

Expand All @@ -80,7 +80,7 @@ describe('Tx details', () => {
cy.get(ss.txRemovedVotes).should('not.exist');
// cy.get(ss.txFee).should('have.text', '25');
cy.get(ss.txConfirmations).contains(/^\d/);
cy.get(ss.txId).contains(/^\d{19}/);
cy.get(ss.txId).contains(/^\d{1,20}/);
cy.get(ss.txReference).should('have.text', '-');
});

Expand All @@ -95,7 +95,7 @@ describe('Tx details', () => {
cy.get(ss.txRemovedVotes).should('not.exist');
cy.get(ss.txFee).should('have.text', '5');
cy.get(ss.txConfirmations).contains(/^\d/);
cy.get(ss.txId).contains(/^\d{19}/);
cy.get(ss.txId).contains(/^\d{1,20}/);
cy.get(ss.txReference).should('have.text', '-');
});
});
4 changes: 2 additions & 2 deletions test/cypress/support/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ Cypress.Commands.add('addLocalStorage', (item, key, value) => {
});

Cypress.Commands.add('autologin', (passphrase, network) => {
localStorage.setItem('autologinUrl', network);
localStorage.setItem('autologinKey', passphrase);
localStorage.setItem('liskCoreUrl', network);
localStorage.setItem('loginKey', passphrase);
});


Expand Down

0 comments on commit a9672cc

Please sign in to comment.