Skip to content

Commit

Permalink
Password change fixes on sub wallets (fixes #213)
Browse files Browse the repository at this point in the history
  • Loading branch information
Gregory Saive committed Apr 7, 2020
1 parent dbe3456 commit b1dd9dd
Show file tree
Hide file tree
Showing 8 changed files with 39 additions and 37 deletions.
15 changes: 6 additions & 9 deletions __tests__/services/WalletService.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {NetworkType, Account, Password, EncryptedPrivateKey} from 'symbol-sdk'
import {NetworkType, Account, Password} from 'symbol-sdk'
import {WalletService} from '@/services/WalletService'
import {MnemonicPassPhrase} from 'symbol-hd-wallets'
import {wallet1Params, WalletsModel1} from '@MOCKS/Wallets'
Expand Down Expand Up @@ -119,19 +119,16 @@ describe('services/WalletServices', () => {
const initialEncIv = WalletsModel1.values.get('encIv')

// update the model
const updatedWallet = service.updateWalletPassword(
const encryptedKey = service.updateWalletPassword(
WalletsModel1, wallet1Params.password, new Password('password2'),
)

// decrypt the new model's private key
const newEncPrivate = updatedWallet.values.get('encPrivate')
const newEncIv = updatedWallet.values.get('encIv')
const privateKey = new EncryptedPrivateKey(newEncPrivate, newEncIv)
.decrypt(new Password('password2'))
const privateKey = encryptedKey.decrypt(new Password('password2'))

// assert the encrypted private key changed
expect(newEncPrivate).not.toBe(initialEncPrivate)
expect(newEncIv).not.toBe(initialEncIv)
expect(encryptedKey.encryptedKey).not.toBe(initialEncPrivate)
expect(encryptedKey.iv).not.toBe(initialEncIv)

// assert the plain private key did not change
expect(privateKey).toBe(wallet1Params.privateKey)
Expand Down
7 changes: 6 additions & 1 deletion __tests__/store/Account.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
import {getFakeModel} from '@MOCKS/Database'
import AccountStore from '@/store/Account'
import flushPromises from 'flush-promises'

describe('store/Account', () => {
describe('action "RESET_STATE" should', () => {
Expand All @@ -33,18 +34,22 @@ describe('store/Account', () => {
})

describe('action "LOG_OUT" should', () => {
test('dispatch "RESET_STATE"', () => {
test('dispatch "RESET_STATE"', async (done) => {
// prepare
const dispatch = jest.fn()
const rootGetters = {'wallet/currentWallet': getFakeModel('1234')}

// act
AccountStore.actions.LOG_OUT({dispatch, rootGetters})
await flushPromises()

// assert
expect(dispatch).toHaveBeenCalled()
expect(dispatch).toHaveBeenCalledWith('wallet/uninitialize', {'address': undefined}, {root: true})
expect(dispatch).toHaveBeenCalledWith('wallet/SET_KNOWN_WALLETS', [], {root: true})
expect(dispatch).toHaveBeenCalledWith('wallet/RESET_CURRENT_WALLET', undefined, {root: true})
expect(dispatch).toHaveBeenCalledWith('RESET_STATE')
done()
})
})

Expand Down
4 changes: 2 additions & 2 deletions src/components/PageNavigator/PageNavigatorTs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ export class PageNavigatorTs extends Vue {
* Executes action of logout
* @return {void}
*/
public logout() {
this.$store.dispatch('account/LOG_OUT')
public async logout() {
await this.$store.dispatch('account/LOG_OUT')
this.$router.push({name: 'accounts.login'})
}
}
11 changes: 4 additions & 7 deletions src/services/WalletService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -379,11 +379,11 @@ export class WalletService extends AbstractService {
wallet: WalletsModel,
oldPassword: Password,
newPassword: Password,
): WalletsModel {
): EncryptedPrivateKey {
// Password modification is not allowed for hardware wallets
if (wallet.values.get('type') !== WalletType.fromDescriptor('Seed')
&& wallet.values.get('type') !== WalletType.fromDescriptor('Pk')) {
return wallet
throw new Error('Hardware wallet password cannot be changed')
}

// Get the private key
Expand All @@ -402,10 +402,7 @@ export class WalletService extends AbstractService {
wallet.objects.address.networkType,
)

// Update the wallet model
wallet.values.set('encPrivate', newSimpleWallet.encryptedPrivateKey.encryptedKey)
wallet.values.set('encIv', newSimpleWallet.encryptedPrivateKey.iv)

return wallet
// return new encrypted private key
return newSimpleWallet.encryptedPrivateKey
}
}
8 changes: 5 additions & 3 deletions src/store/Account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,12 @@ export default {
commit('currentAccount', null)
commit('setAuthenticated', false)
},
LOG_OUT({dispatch, rootGetters}) {
async LOG_OUT({dispatch, rootGetters}): Promise<void> {
const currentWallet = rootGetters['wallet/currentWallet']
dispatch('wallet/uninitialize', {address: currentWallet.values.get('address')}, {root: true})
return dispatch('RESET_STATE')
await dispatch('wallet/uninitialize', {address: currentWallet.values.get('address')}, {root: true})
await dispatch('wallet/SET_KNOWN_WALLETS', [], {root: true})
await dispatch('wallet/RESET_CURRENT_WALLET', undefined, {root: true})
await dispatch('RESET_STATE')
},
async SET_CURRENT_ACCOUNT({commit, dispatch}, currentAccountModel) {

Expand Down
1 change: 0 additions & 1 deletion src/store/Wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,6 @@ export default {
await dispatch('RESET_BALANCES', which)
await dispatch('RESET_MULTISIG')
await dispatch('RESET_TRANSACTIONS')
await dispatch('RESET_CURRENT_WALLET')
commit('setInitialized', false)
}
await Lock.uninitialize(callback, {getters})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,8 @@ export class FormAccountPasswordUpdateTs extends Vue {
try {
const service = new AccountService(this.$store)
const repository = new AccountsRepository()
const accountModel = this.currentAccount
const newPassword = new Password(this.formItems.password)
const accountModel = this.currentAccount

// - create new password hash
const passwordHash = service.getPasswordHash(newPassword)
Expand All @@ -132,25 +132,27 @@ export class FormAccountPasswordUpdateTs extends Vue {
const oldSeed = accountModel.values.get('seed')
const plainSeed = AESEncryptionService.decrypt(oldSeed , oldPassword)
const newSeed = AESEncryptionService.encrypt(plainSeed, newPassword)
this.currentAccount.values.set('seed', newSeed)
accountModel.values.set('seed', newSeed)

// - update in storage
repository.update(accountModel.getIdentifier(), accountModel.values)
repository.update(this.currentAccount.getIdentifier(), accountModel.values)

// - update wallets passwords
const walletsRepository = new WalletsRepository()
const walletService = new WalletService()

const walletIdentifiers = accountModel.values.get('wallets')
const walletModels = walletIdentifiers.map(id => walletsRepository.read(id))
const walletModels = walletIdentifiers.map(id => walletsRepository.read(id)).filter(
(v, i, s) => s.indexOf(v) === i,
)

for (const model of walletModels) {
const updatedModel = walletService.updateWalletPassword(model, oldPassword, newPassword)
const updatedValues = new Map<string, string>([
[ 'encPrivate', updatedModel.values.get('encPrivate') ],
[ 'encIv', updatedModel.values.get('encIv') ],
])
walletsRepository.update(model.getIdentifier(), updatedValues)
const encryptedKey = walletService.updateWalletPassword(model, oldPassword, newPassword)

model.values.set('encPrivate', encryptedKey.encryptedKey)
model.values.set('encIv', encryptedKey.iv)

walletsRepository.update(model.getIdentifier(), model.values)
}

// - update state and finalize
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ export class FormSubWalletCreationTs extends Vue {
/**
* When account is unlocked, the sub wallet can be created
*/
public onAccountUnlocked(account: Account, password: Password) {
public async onAccountUnlocked(account: Account, password: Password) {
this.currentPassword = password

// - interpret form items
Expand Down Expand Up @@ -246,9 +246,9 @@ export class FormSubWalletCreationTs extends Vue {
)

// - update app state
this.$store.dispatch('account/ADD_WALLET', subWallet)
this.$store.dispatch('wallet/SET_CURRENT_WALLET', {model: subWallet})
this.$store.dispatch('wallet/SET_KNOWN_WALLETS', wallets)
await this.$store.dispatch('account/ADD_WALLET', subWallet)
await this.$store.dispatch('wallet/SET_CURRENT_WALLET', {model: subWallet})
await this.$store.dispatch('wallet/SET_KNOWN_WALLETS', wallets)
this.$store.dispatch('notification/ADD_SUCCESS', NotificationType.OPERATION_SUCCESS)
this.$emit('submit', this.formItems)
}
Expand Down

0 comments on commit b1dd9dd

Please sign in to comment.