Skip to content
This repository has been archived by the owner on Jun 7, 2023. It is now read-only.

Commit

Permalink
Handle read permissions on runtime when seedvault is imported (Androi…
Browse files Browse the repository at this point in the history
…d) (#393)

Fixes #376
  • Loading branch information
laumair authored and rajivshah3 committed Sep 21, 2018
1 parent 12c972e commit 637c5a8
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 3 deletions.
@@ -0,0 +1,81 @@
import assign from 'lodash/assign';
import noop from 'lodash/noop';
import React from 'react';
import { PermissionsAndroid } from 'react-native';
import { shallow } from 'enzyme';
import { SeedVaultImportComponent } from 'ui/components/SeedVaultImportComponent';

jest.mock('rn-fetch-blob', () => ({ DocumentDir: () => {} }));
jest.mock('nodejs-mobile-react-native', () => ({
start: () => {},
channel: {
addListener: () => {},
removeListener: () => {},
},
}));

const getProps = (overrides) =>
assign(
{},
{
theme: { input: {}, body: {}, primary: {} },
t: () => '',
generateAlert: noop,
openPasswordValidationModal: noop,
onSeedImport: noop,
onRef: noop,
},
overrides,
);

describe('Testing SeedVaultImportComponent component', () => {
describe('instance methods', () => {
describe('when called', () => {
describe('#grantPermissions', () => {
beforeEach(() => {
jest.mock('PermissionsAndroid', () => ({
request: jest.fn(() => Promise.resolve(true)),
PERMISSIONS: {},
RESULTS: {
GRANTED: 'granted',
},
}));
});

describe('when read permission is already granted', () => {
it('should resolve true', () => {
const props = getProps();

const instance = shallow(<SeedVaultImportComponent {...props} />).instance();

return instance.grantPermissions().then((result) => expect(result).toEqual(true));
});
});

describe('when read permission is granted by user', () => {
it('should resolve "granted"', () => {
PermissionsAndroid.request.mockReturnValueOnce(Promise.resolve('granted'));
const props = getProps();

const instance = shallow(<SeedVaultImportComponent {...props} />).instance();

return instance.grantPermissions().then((result) => expect(result).toEqual('granted'));
});
});

describe('when read permission is denied by user', () => {
it('should throw an error with message "Read permissions not granted."', () => {
PermissionsAndroid.request.mockReturnValueOnce(Promise.resolve('denied'));
const props = getProps();

const instance = shallow(<SeedVaultImportComponent {...props} />).instance();

return instance
.grantPermissions()
.catch((err) => expect(err).toEqual(new Error('Read permissions not granted.')));
});
});
});
});
});
});
23 changes: 20 additions & 3 deletions src/mobile/src/ui/components/SeedVaultImportComponent.js
@@ -1,5 +1,5 @@
import React, { Component } from 'react';
import { View, Text, StyleSheet, TouchableOpacity } from 'react-native';
import { View, Text, StyleSheet, TouchableOpacity, PermissionsAndroid } from 'react-native';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { DocumentPicker } from 'react-native-document-picker';
Expand Down Expand Up @@ -81,6 +81,22 @@ export class SeedVaultImportComponent extends Component {
return nodejs.channel.send('import:' + seedVaultString + ':' + password);
}

/**
* Grant storage read permissions for android
*
* @method grantPermissions
* @returns {Promise}
*/
grantPermissions() {
return PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE).then((granted) => {
if (granted === true || granted === PermissionsAndroid.RESULTS.GRANTED) {
return Promise.resolve(granted);
}

throw new Error('Read permissions not granted.');
});
}

/**
* Opens document picker, reads chosen file and opens password validation modal
* @method importSeedVault
Expand All @@ -105,8 +121,9 @@ export class SeedVaultImportComponent extends Component {
if (path.startsWith('file://')) {
path = path.slice(7);
}
RNFetchBlob.fs
.readFile(path, 'ascii')

(isAndroid ? this.grantPermissions() : Promise.resolve())
.then(() => RNFetchBlob.fs.readFile(path, 'ascii'))
.then((data) => {
this.setState({ seedVault: data });
this.props.openPasswordValidationModal();
Expand Down

0 comments on commit 637c5a8

Please sign in to comment.