diff --git a/.nvimrc b/.nvimrc new file mode 120000 index 0000000..1490f7a --- /dev/null +++ b/.nvimrc @@ -0,0 +1 @@ +.vimrc \ No newline at end of file diff --git a/.vimrc b/.vimrc new file mode 100644 index 0000000..756e065 --- /dev/null +++ b/.vimrc @@ -0,0 +1,2 @@ +set autoread +set path+=.,public/**,src/**,test/** diff --git a/public/detect_linux.sh b/public/detect_linux.sh index 593b880..a94c237 100644 --- a/public/detect_linux.sh +++ b/public/detect_linux.sh @@ -91,6 +91,9 @@ if [ "$DISTNAME" = "unknown" ]; then elif [ "$VERSION_ID" = "15.1" ]; then DISTNAME=debian DISTVER=9 + elif [ "$VERSION_ID" = "15.2" ]; then + DISTNAME=debian + DISTVER=9 else resetDistVer fi diff --git a/src/App.js b/src/App.js index eb52b3e..b9bf6d2 100644 --- a/src/App.js +++ b/src/App.js @@ -110,8 +110,9 @@ class App extends IPCContainer { const remoteSupported = this.props.LocationsLookup[selectedVersion] && this.props.LocationsLookup[selectedVersion].supports_remote; - const s3Supported = this.props.LocationsLookup[selectedVersion] && + let s3Supported = this.props.LocationsLookup[selectedVersion] && this.props.LocationsLookup[selectedVersion].s3_support; + //s3Supported = true; const skynetSupported = this.props.LocationsLookup[selectedVersion] && this.props.LocationsLookup[selectedVersion].skynet_support; @@ -174,6 +175,7 @@ class App extends IPCContainer { const configDisplay = createModalConditionally(showConfig, ); const confirmDisplay = createModalConditionally(this.props.DisplayConfirmYesNo, ); const dependencyDisplay = createModalConditionally(showDependencies, diff --git a/src/constants.js b/src/constants.js index b9aeaca..532697f 100644 --- a/src/constants.js +++ b/src/constants.js @@ -1,7 +1,6 @@ -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.DEV_PUBLIC_KEY = '-----BEGIN PUBLIC KEY-----\n' + +Object.defineProperty(exports, '__esModule', {value: true}); +exports.DEV_PUBLIC_KEY = + '-----BEGIN PUBLIC KEY-----\n' + 'MIIEIjANBgkqhkiG9w0BAQEFAAOCBA8AMIIECgKCBAEKfZmq5mMAtD4kSt2Gc/5J\n' + 'H+HHTYtUZE6YYvsvz8TNG/bNL67ZtNRyaoMyhLTfIN4rPBNLUfD+owNS+u5Yk+lS\n' + 'ZLYyOuhoCZIFefayYqKLr42G8EeuRbx0IMzXmJtN0a4rqxlWhkYufJubpdQ+V4DF\n' + @@ -30,10 +29,15 @@ exports.DEV_PUBLIC_KEY = '-----BEGIN PUBLIC KEY-----\n' + const REPERTORY_BRANCH = '1.3.x_branch'; const REPERTORY_UI_BRANCH = '1.3.x_branch'; -exports.RELEASES_URL = 'https://bitbucket.org/blockstorage/repertory/raw/' + REPERTORY_BRANCH + '/releases_1.3.json'; -exports.UI_RELEASES_URL = 'https://bitbucket.org/blockstorage/repertory-ui/raw/' + REPERTORY_UI_BRANCH + '/releases.json'; +exports.RELEASES_URL = 'https://bitbucket.org/blockstorage/repertory/raw/' + + REPERTORY_BRANCH + '/releases_1.3.json'; +exports.UI_RELEASES_URL = + 'https://bitbucket.org/blockstorage/repertory-ui/raw/' + + REPERTORY_UI_BRANCH + '/releases.json'; -exports.LINUX_DETECT_SCRIPT_URL = 'https://bitbucket.org/blockstorage/repertory/raw/' + REPERTORY_BRANCH + '/detect_linux2.sh'; +exports.LINUX_DETECT_SCRIPT_URL = + 'https://bitbucket.org/blockstorage/repertory/raw/' + REPERTORY_BRANCH + + '/detect_linux2.sh'; exports.LINUX_SELECTABLE_PLATFORMS = [ 'centos7', @@ -50,7 +54,6 @@ exports.DATA_LOCATIONS = { exports.PROVIDER_LIST = [ 'Sia', 'Skynet', - 'S3', 'ScPrime', ]; diff --git a/src/containers/AddMount/AddMount.css b/src/containers/AddMount/AddMount.css new file mode 100644 index 0000000..399824e --- /dev/null +++ b/src/containers/AddMount/AddMount.css @@ -0,0 +1,13 @@ +.AddRemoteMount { + margin: 0; + padding: 0; +} + +.AddMountButtons { + display: flex; + flex-direction: row; +} + +.AddMountButton { + flex: 1; +} diff --git a/src/containers/AddMount/AddMount.js b/src/containers/AddMount/AddMount.js new file mode 100644 index 0000000..6af67bf --- /dev/null +++ b/src/containers/AddMount/AddMount.js @@ -0,0 +1,222 @@ +import React from 'react'; +import {Component} from 'react'; +import './AddMount.css'; +import {connect} from 'react-redux'; +import Button from '../../components/UI/Button/Button'; +import Box from '../../components/UI/Box/Box'; +import Text from '../../components/UI/Text/Text'; +import {notifyError} from '../../redux/actions/error_actions'; +import {addRemoteMount, addS3Mount} from '../../redux/actions/mount_actions'; +import {createModalConditionally} from '../../utils'; + +const mapStateToProps = state => { + return { + RemoteMounts: state.mounts.RemoteMounts, + S3Mounts: state.mounts.S3Mounts, + }; +}; + +const mapDispatchToProps = dispatch => { + return { + addRemoteMount: (hostNameOrIp, port, token) => dispatch(addRemoteMount(hostNameOrIp, port, token)), + addS3Mount: (name, accessKey, secretKey, region, bucketName) => dispatch(addS3Mount(name, accessKey, secretKey, region, bucketName)), + notifyError: (msg, critical, callback) => dispatch(notifyError(msg, critical, callback)), + } +}; + +const default_state = { + AccessKey: '', + BucketName: '', + DisplayRemote: false, + DisplayS3: false, + HostNameOrIp: '', + Name: '', + Port: 20000, + Region: 'any', + SecretKey: '', + Token: '', +}; + +export default connect(mapStateToProps, mapDispatchToProps)(class extends Component { + state = { + ...default_state, + }; + + addRemoteMount = () => { + if (this.state.HostNameOrIp.length === 0) { + this.props.notifyError('Hostname or IP cannot be empty.'); + } else { + const provider = 'Remote' + this.state.HostNameOrIp + ':' + this.state.Port; + if (this.props.RemoteMounts.includes(provider)) { + this.props.notifyError('Remote host already exists'); + } else { + this.setState({ + Display: false + }, () => { + this.props.addRemoteMount(this.state.HostNameOrIp, this.state.Port, this.state.Token); + this.setState({ + ...default_state, + }); + }); + } + } + }; + + addS3Mount = () => { + + }; + + handleAddS3Mount = () => { + this.setState({ + DisplayRemote: false, + DisplayS3: true, + }); + }; + + handleAddRemoteMount = () => { + this.setState({ + DisplayRemote: true, + DisplayS3: false, + }); + }; + + render() { + const displayAddRemote = createModalConditionally(this.state.DisplayRemote, ( + +

Add Remote + Mount

+ + this.setState({HostNameOrIp: e.target.value.trim()})} + className={'ConfigurationItemInput'} + type={'text'} + value={this.state.HostNameOrIp}/> +
+ + this.setState({Port: e.target.value})} + className={'ConfigurationItemInput'} + type={'number'} + value={this.state.Port}/> +
+ + this.setState({Token: e.target.value})} + className={'ConfigurationItemInput'} + type={'text'} + value={this.state.Token}/> +
+ + + + + + + +
+ + + +
+ + )); + + const displayAddS3 = createModalConditionally(this.state.DisplayS3, ( + +

Add S3 + Mount

+ + this.setState({Name: e.target.value.trim()})} + className={'ConfigurationItemInput'} + style={{width: '100%'}} + type={'text'} + value={this.state.Name}/> +
+ + this.setState({BucketName: e.target.value})} + className={'ConfigurationItemInput'} + style={{width: '100%'}} + type={'text'} + value={this.state.BucketName}/> +
+ + this.setState({Region: e.target.value})} + className={'ConfigurationItemInput'} + type={'text'} + value={this.state.Region}/> +
+ +
+ +
+ +
+
+ this.setState({AccessKey: e.target.value})} + className={'ConfigurationItemInput'} + type={'text'} + value={this.state.AccessKey}/> +
+ this.setState({SecretKey: e.target.value})} + className={'ConfigurationItemInput'} + type={'text'} + value={this.state.SecretKey}/> +
+ +
+ + + + + + + +
+ + + +
+ + )); + + return ( +
+ {displayAddRemote} + {displayAddS3} +
+ {this.props.remoteSupported ? + : null} + {this.props.remoteSupported && this.props.s3Supported ? +
: null} + {this.props.s3Supported ? + : null} +
+
+ ); + } +}); diff --git a/src/containers/AddRemoteMount/AddRemoteMount.css b/src/containers/AddRemoteMount/AddRemoteMount.css deleted file mode 100644 index 5a01963..0000000 --- a/src/containers/AddRemoteMount/AddRemoteMount.css +++ /dev/null @@ -1,4 +0,0 @@ -.AddRemoteMount { - margin: 0; - padding: 0; -} \ No newline at end of file diff --git a/src/containers/AddRemoteMount/AddRemoteMount.js b/src/containers/AddRemoteMount/AddRemoteMount.js deleted file mode 100644 index 5cd9252..0000000 --- a/src/containers/AddRemoteMount/AddRemoteMount.js +++ /dev/null @@ -1,117 +0,0 @@ -import React from 'react'; -import {Component} from 'react'; -import './AddRemoteMount.css'; -import {connect} from 'react-redux'; -import Button from '../../components/UI/Button/Button'; -import Box from '../../components/UI/Box/Box'; -import Text from '../../components/UI/Text/Text'; -import {notifyError} from '../../redux/actions/error_actions'; -import {addRemoteMount} from '../../redux/actions/mount_actions'; -import {createModalConditionally} from '../../utils'; - -const mapStateToProps = state => { - return { - RemoteMounts: state.mounts.RemoteMounts, - }; -}; - -const mapDispatchToProps = dispatch => { - return { - addRemoteMount: (hostNameOrIp, port, token) => dispatch(addRemoteMount(hostNameOrIp, port, token)), - notifyError: (msg, critical, callback) => dispatch(notifyError(msg, critical, callback)), - } -}; - -export default connect(mapStateToProps, mapDispatchToProps)(class extends Component { - state = { - Display: false, - HostNameOrIp: '', - Port: 20000, - Token: '', - }; - - addRemoteMount = () => { - if (this.state.HostNameOrIp.length === 0) { - this.props.notifyError('Hostname or IP cannot be empty.'); - } else { - const provider = 'Remote' + this.state.HostNameOrIp + ':' + this.state.Port; - if (this.props.RemoteMounts.includes(provider)) { - this.props.notifyError('Remote host already exists'); - } else { - this.setState({ - Display: false - }, () => { - this.props.addRemoteMount(this.state.HostNameOrIp, this.state.Port, this.state.Token); - this.setState({ - HostNameOrIp: '', - Port: 20000, - Token: '', - }); - }); - } - } - }; - - handleAddRemoteMount = () => { - this.setState({ - Display: true, - }); - }; - - render() { - const displayAdd = createModalConditionally(this.state.Display, ( - -

Add Remote Mount

- - this.setState({HostNameOrIp: e.target.value.trim()})} - className={'ConfigurationItemInput'} - type={'text'} - value={this.state.HostNameOrIp}/> -
- - this.setState({Port: e.target.value})} - className={'ConfigurationItemInput'} - type={'number'} - value={this.state.Port}/> -
- - this.setState({Token: e.target.value})} - className={'ConfigurationItemInput'} - type={'text'} - value={this.state.Token}/> -
- - - - - - - -
- - - -
- - )); - - return ( -
- {displayAdd} - -
- ); - } -}); diff --git a/src/containers/Configuration/Configuration.js b/src/containers/Configuration/Configuration.js index 48e9a55..d779116 100644 --- a/src/containers/Configuration/Configuration.js +++ b/src/containers/Configuration/Configuration.js @@ -82,6 +82,7 @@ class Configuration extends IPCContainer { this.sendRequest(Constants.IPC_Get_Config_Template, { Provider: this.props.DisplayConfiguration, Remote: this.props.DisplayRemoteConfiguration, + S3: this.props.DisplayS3Configuration, Version: this.props.version, }); } @@ -96,7 +97,7 @@ class Configuration extends IPCContainer { const itemList = Object .keys(config) .map(key => { - const ret = { + return { advanced: template[key] ? template[key].advanced : false, hide_remote: template[key] ? template[key].hide_remote : false, label: key, @@ -108,7 +109,6 @@ class Configuration extends IPCContainer { config[key] : config[key].toString(), }; - return ret; }) .filter(i=> { let ret = template[i.label]; @@ -193,6 +193,7 @@ class Configuration extends IPCContainer { this.sendRequest(Constants.IPC_Get_Config, { Provider: this.props.DisplayConfiguration, Remote: this.props.DisplayRemoteConfiguration, + S3: this.props.DisplayS3Configuration, Version: this.props.version, }); }); @@ -240,6 +241,7 @@ class Configuration extends IPCContainer { Items: changedItems, Provider: this.props.DisplayConfiguration, Remote: this.props.DisplayRemoteConfiguration, + S3: this.props.DisplayS3Configuration, Version: this.props.version, }); }); @@ -361,6 +363,7 @@ const mapStateToProps = state => { return { DisplayConfiguration: state.mounts.DisplayConfiguration, DisplayRemoteConfiguration: state.mounts.DisplayRemoteConfiguration, + DisplayS3Configuration: state.mounts.DisplayS3Configuration, Platform: state.common.Platform, } }; diff --git a/src/containers/MountItems/MountItem/MountItem.js b/src/containers/MountItems/MountItem/MountItem.js index 3f2d172..9af80ec 100644 --- a/src/containers/MountItems/MountItem/MountItem.js +++ b/src/containers/MountItems/MountItem/MountItem.js @@ -31,7 +31,7 @@ const mapStateToProps = (state, ownProps) => { const mapDispatchToProps = dispatch => { return { - displayConfiguration: (provider, remote) => dispatch(displayConfiguration(provider, remote)), + displayConfiguration: (provider, remote, s3) => dispatch(displayConfiguration(provider, remote, s3)), displaySkynetExport: display => dispatch(displaySkynetExport(display)), displaySkynetImport: display => dispatch(displaySkynetImport(display)), removeRemoteMount: provider => dispatch(removeRemoteMount(provider)), @@ -63,7 +63,9 @@ export default connect(mapStateToProps, mapDispatchToProps)(props => { rowSpan={6}> props.displayConfiguration(props.provider, props.remote) : e=>{e.preventDefault();}} + onClick={props.MState.AllowMount ? () => props.displayConfiguration(props.provider, props.remote, props.s3) : e => { + e.preventDefault(); + }} src={configureImage} style={{padding: 0, border: 0, margin: 0, ...pointer}} width={'16px'}/> @@ -120,12 +122,13 @@ export default connect(mapStateToProps, mapDispatchToProps)(props => { width={19}/>; const actionsDisplay = ( - ); diff --git a/src/containers/MountItems/MountItems.js b/src/containers/MountItems/MountItems.js index bc0265b..452ba88 100644 --- a/src/containers/MountItems/MountItems.js +++ b/src/containers/MountItems/MountItems.js @@ -1,5 +1,5 @@ import React from 'react'; -import AddRemoteMount from '../AddRemoteMount/AddRemoteMount'; +import AddMount from '../AddMount/AddMount'; import Box from '../../components/UI/Box/Box'; import Button from '../../components/UI/Button/Button'; import {connect} from 'react-redux'; @@ -94,7 +94,7 @@ class MountItems extends IPCContainer { } }; - displayRetryMount = (provider, remote, mountLocation, msg) => { + displayRetryMount = (provider, remote, s3, mountLocation, msg) => { if (!this.state.RetryItems[provider]) { let retryItems = { ...this.state.RetryItems @@ -121,7 +121,7 @@ class MountItems extends IPCContainer { const retrySeconds = retryItems[provider].RetrySeconds - 1; if (retrySeconds === 0) { this.cancelRetryMount(provider, () => { - this.handleMountUnMount(provider, remote,true, mountLocation); + this.handleMountUnMount(provider, remote, s3, true, mountLocation); }); } else { retryItems[provider].RetrySeconds = retrySeconds; @@ -152,17 +152,18 @@ class MountItems extends IPCContainer { this.props.setProviderState(provider, state); }; - handleMountUnMount = (provider, remote, mount, location) => { + handleMountUnMount = (provider, remote, s3, mount, location) => { if (!location || (location.trim().length === 0)) { this.props.notifyError('Mount location is not set'); } else { let allowAction = true; if (mount) { - let result = remote || provider === 'S3' || provider === 'Skynet' ? + let result = remote || s3 || provider === 'Skynet' ? {Valid: true, Success: true} : this.sendSyncRequest(Constants.IPC_Check_Daemon_Version, { Provider: provider, Remote: remote, + S3: s3, Version: this.props.InstalledVersion }).data; if (result.Success) { @@ -179,11 +180,11 @@ class MountItems extends IPCContainer { } else { allowAction = false; if ((result.Code === new Uint32Array([-1])[0]) || (result.Code === new Uint8Array([-1])[0])) { - this.displayRetryMount(provider, remote, location, 'Failed to connect to ' + provider + ' daemon'); + this.displayRetryMount(provider, remote, s3, location, 'Failed to connect to ' + provider + ' daemon'); } else if ((result.Code === new Uint32Array([-3])[0]) || (result.Code === new Uint8Array([-3])[0])) { - this.displayRetryMount(provider, remote, location, 'Incompatible ' + provider + ' daemon. Please upgrade ' + provider + '.'); + this.displayRetryMount(provider, remote, s3, location, 'Incompatible ' + provider + ' daemon. Please upgrade ' + provider + '.'); } else { - this.displayRetryMount(provider, remote, location, 'Version check failed: ' + result.Error); + this.displayRetryMount(provider, remote, s3, location, 'Version check failed: ' + result.Error); } } } else { @@ -191,7 +192,7 @@ class MountItems extends IPCContainer { if (this.props.Platform === 'win32') { this.props.notifyError('Failed to launch repertory. Please install Microsoft Visual C++ Redistributable for Visual Studio 2015, 2017 and 2019.'); } else { - this.displayRetryMount(provider, remote, location, 'Version check failed: ' + result.Error); + this.displayRetryMount(provider, remote, s3, location, 'Version check failed: ' + result.Error); } } } @@ -205,6 +206,7 @@ class MountItems extends IPCContainer { Location: location, Provider: provider, Remote: remote, + S3: s3, Version: this.props.InstalledVersion, }); } else { @@ -212,6 +214,7 @@ class MountItems extends IPCContainer { Location: location, Provider: provider, Remote: remote, + S3: s3, Version: this.props.InstalledVersion, }); } @@ -221,8 +224,7 @@ class MountItems extends IPCContainer { getProviderList = providersOnly => { const providerList = Constants.PROVIDER_LIST.filter(i => { - return ((i === 'S3') && this.props.s3Supported) || - ((i === 'Skynet') && this.props.skynetSupported) || + return ((i === 'Skynet') && this.props.skynetSupported) || ((i === 'ScPrime') && this.props.scPrimeSupported) || ((i === 'Sia') && this.props.siaSupported); }); @@ -232,9 +234,15 @@ class MountItems extends IPCContainer { remoteList = [...this.props.RemoteMounts]; } + let s3List = []; + if (this.props.s3Supported && !providersOnly) { + s3List = [...this.props.S3Mounts]; + } + return [ ...providerList, ...remoteList, + ...s3List, ]; }; @@ -337,7 +345,11 @@ class MountItems extends IPCContainer { retryDisplay = ( -

Mount Failed

+

Mount Failed

{retryList}
@@ -345,8 +357,10 @@ class MountItems extends IPCContainer { } let footerItems = []; - if (this.props.remoteSupported) { - footerItems.push(); + if (this.props.remoteSupported || this.props.s3Supported) { + footerItems.push(); } else { footerItems.push(
); @@ -380,15 +394,31 @@ class MountItems extends IPCContainer { items.push(
) } - items.splice(items.length - 1, 1); - } else { - items.splice(items.length - 1, 1) } + if (this.props.s3Supported) { + for (const provider of this.props.S3Mounts) { + items.push(( + this.handleMountLocationChanged(provider, e.target.value)} + clicked={this.handleMountUnMount} + key={'it_' + items.length} + provider={provider} + s3/> + )); + items.push(
) + } + } + + items.splice(items.length - 1, 1); + return (
{retryDisplay} -
+
{items}
@@ -406,6 +436,7 @@ const mapStateToProps = state => { Platform: state.common.Platform, ProviderState: state.mounts.ProviderState, RemoteMounts: state.mounts.RemoteMounts, + S3Mounts: state.mounts.S3Mounts, } }; diff --git a/src/helpers.js b/src/helpers.js index 04bac4a..e3e8868 100644 --- a/src/helpers.js +++ b/src/helpers.js @@ -213,10 +213,14 @@ const _getDataDirectory = () => { return _resolvePath(Constants.DATA_LOCATIONS[os.platform()]); }; -const _getDefaultRepertoryArgs = (provider, remote) => { +const _getDefaultRepertoryArgs = (provider, remote, s3) => { const providerLower = provider.toLowerCase(); const args = []; - if (remote) { + if (s3) { + args.push('-s3'); + args.push('-na'); + args.push(provider.substr(2)); + } else if (remote) { args.push('-rm'); args.push(provider.substr(6)); } else if (Constants.PROVIDER_ARG[providerLower] && (Constants.PROVIDER_ARG[providerLower].length > 0)) { @@ -276,7 +280,7 @@ module.exports.checkDaemonVersion = (version, provider) => { windowsHide: true, }; - const args = _getDefaultRepertoryArgs(provider, false); + const args = _getDefaultRepertoryArgs(provider); args.push('-cv'); const process = new spawn(repertoryExec.cmd, args, processOptions); @@ -368,7 +372,9 @@ module.exports.detectRepertoryMounts = (version, providerList) => { windowsHide: true, }; - const args = _getDefaultRepertoryArgs(provider, !Constants.PROVIDER_LIST.includes(provider)); + const args = _getDefaultRepertoryArgs(provider, + !Constants.PROVIDER_LIST.includes(provider) && provider.toLowerCase().startsWith('remote'), + !Constants.PROVIDER_LIST.includes(provider) && provider.toLowerCase().startsWith('s3')); args.push('-status'); const process = new spawn(repertoryExec.cmd, args, processOptions); @@ -560,7 +566,7 @@ module.exports.executeScript = script => { }); }; -module.exports.executeMount = (version, provider, remote, location, exitCallback) => { +module.exports.executeMount = (version, provider, remote, s3, location, exitCallback) => { return new Promise((resolve) => { const repertoryExec = _getRepertoryExec(version); const processOptions = { @@ -570,7 +576,7 @@ module.exports.executeMount = (version, provider, remote, location, exitCallback stdio: 'ignore', }; - const args = _getDefaultRepertoryArgs(provider, remote); + const args = _getDefaultRepertoryArgs(provider, remote, s3); if ((os.platform() === 'linux') || (os.platform() === 'darwin')) { args.push('-o'); @@ -645,7 +651,7 @@ module.exports.exportSkylinks = (version, paths) => { }); }; -module.exports.getConfig = (version, provider, remote) => { +module.exports.getConfig = (version, provider, remote, s3) => { return new Promise((resolve, reject) => { const repertoryExec = _getRepertoryExec(version); const processOptions = { @@ -655,7 +661,7 @@ module.exports.getConfig = (version, provider, remote) => { windowsHide: true, }; - const args = _getDefaultRepertoryArgs(provider, remote); + const args = _getDefaultRepertoryArgs(provider, remote, s3); args.push('-dc'); const process = new spawn(repertoryExec.cmd, args, processOptions); @@ -689,7 +695,7 @@ module.exports.getConfig = (version, provider, remote) => { }); }; -module.exports.getConfigTemplate = (version, provider, remote) => { +module.exports.getConfigTemplate = (version, provider, remote, s3) => { return new Promise((resolve, reject) => { const repertoryExec = _getRepertoryExec(version); const processOptions = { @@ -699,7 +705,7 @@ module.exports.getConfigTemplate = (version, provider, remote) => { windowsHide: true, }; - const args = _getDefaultRepertoryArgs(provider, remote); + const args = _getDefaultRepertoryArgs(provider, remote, s3); args.push('-gt'); const process = new spawn(repertoryExec.cmd, args, processOptions); @@ -969,7 +975,7 @@ module.exports.removeDirectoryRecursively = _removeDirectoryRecursively; module.exports.resolvePath = _resolvePath; -module.exports.setConfigValue = (name, value, provider, remote, version) => { +module.exports.setConfigValue = (name, value, provider, remote, s3, version) => { return new Promise((resolve, reject) => { const repertoryExec = _getRepertoryExec(version); const processOptions = { @@ -979,7 +985,7 @@ module.exports.setConfigValue = (name, value, provider, remote, version) => { windowsHide: true, }; - const args = _getDefaultRepertoryArgs(provider, remote); + const args = _getDefaultRepertoryArgs(provider, remote, s3); args.push('-set'); args.push(name); args.push(value); @@ -998,7 +1004,7 @@ module.exports.setConfigValue = (name, value, provider, remote, version) => { }); }; -module.exports.stopMountProcess = (version, provider, remote) => { +module.exports.stopMountProcess = (version, provider, remote, s3) => { return new Promise((resolve, reject) => { const repertoryExec = _getRepertoryExec(version); const processOptions = { @@ -1008,7 +1014,7 @@ module.exports.stopMountProcess = (version, provider, remote) => { windowsHide: true, }; - const args = _getDefaultRepertoryArgs(provider, remote); + const args = _getDefaultRepertoryArgs(provider, remote, s3); args.push('-unmount'); const process = new spawn(repertoryExec.cmd, args, processOptions); @@ -1029,7 +1035,7 @@ module.exports.stopMountProcess = (version, provider, remote) => { }); }; -module.exports.stopMountProcessSync = (version, provider, remote) => { +module.exports.stopMountProcessSync = (version, provider, remote, s3) => { const repertoryExec = _getRepertoryExec(version); const processOptions = { cwd: repertoryExec.working, @@ -1038,7 +1044,7 @@ module.exports.stopMountProcessSync = (version, provider, remote) => { windowsHide: true, }; - const args = _getDefaultRepertoryArgs(provider, remote); + const args = _getDefaultRepertoryArgs(provider, remote, s3); args.push('-unmount'); const process = new spawn(repertoryExec.cmd, args, processOptions); diff --git a/src/redux/actions/mount_actions.js b/src/redux/actions/mount_actions.js index bf7d422..9e99af5 100644 --- a/src/redux/actions/mount_actions.js +++ b/src/redux/actions/mount_actions.js @@ -1,10 +1,9 @@ -import * as Constants from '../../constants'; import {createAction} from '@reduxjs/toolkit'; + +import * as Constants from '../../constants'; import {getIPCRenderer} from '../../utils'; -import { - confirmYesNo, - saveState -} from './common_actions'; + +import {confirmYesNo, saveState} from './common_actions'; import {notifyError} from './error_actions'; export const addRemoteMount = (hostNameOrIp, port, token) => { @@ -23,7 +22,8 @@ export const addRemoteMount = (hostNameOrIp, port, token) => { Version: getState().relver.InstalledVersion, }); } else { - dispatch(notifyError('Failed to set \'RemoteToken\': ' + arg.data.Error)); + dispatch( + notifyError('Failed to set \'RemoteToken\': ' + arg.data.Error)); dispatch(setBusy(false)); } }); @@ -42,15 +42,53 @@ export const addRemoteMount = (hostNameOrIp, port, token) => { }; }; +export const addS3Mount = (name, accessKey, secretKey, region, bucketName) => { + return (dispatch, getState) => { + const ipcRenderer = getIPCRenderer(); + + const provider = 'S3' + name; + dispatch(addS3Mount2(provider)); + dispatch(setBusy(true)); + + ipcRenderer.once(Constants.IPC_Set_Config_Values_Reply, (_, arg) => { + if (arg.data.Success) { + ipcRenderer.send(Constants.IPC_Detect_Mount, { + Provider: provider, + S3Mounts: getState().mounts.S3Mounts, + Version: getState().relver.InstalledVersion, + }); + } else { + dispatch( + notifyError('Failed to create S3 instance: ' + arg.data.Error)); + dispatch(setBusy(false)); + } + }); + + ipcRenderer.send(Constants.IPC_Set_Config_Values, { + Items: [ + {Name: 'S3Config.AccessKey', Value: accessKey}, + {Name: 'S3Config.SecretKey', Value: secretKey}, + {Name: 'S3Config.Region', Value: region}, + {Name: 'S3Config.BucketName', Value: bucketName}, + ], + Provider: provider, + S3: true, + Version: getState().relver.InstalledVersion, + }); + }; +}; + export const addRemoteMount2 = createAction('mounts/addRemoteMount2'); +export const addS3Mount2 = createAction('mounts/addS3Mount2'); export const DISPLAY_CONFIGURATION = 'mounts/displayConfiguration'; -export const displayConfiguration = (provider, remote) => { +export const displayConfiguration = (provider, remote, s3) => { return { type: DISPLAY_CONFIGURATION, payload: { provider, remote, + s3, }, }; }; @@ -58,11 +96,11 @@ export const displayConfiguration = (provider, remote) => { export const removeRemoteMount = provider => { return dispatch => { dispatch(confirmYesNo('Delete [' + provider.substr(6) + ']?')) - .then(confirmed => { - if (confirmed) { - dispatch(removeRemoteMount2(provider)); - } - }); + .then(confirmed => { + if (confirmed) { + dispatch(removeRemoteMount2(provider)); + } + }); }; }; @@ -83,67 +121,40 @@ export const removeRemoteMount3 = createAction('mounts/removeRemoteMount3'); export const RESET_MOUNTS_STATE = 'mounts/resetMountsState'; export const resetMountsState = () => { - return { - type: RESET_MOUNTS_STATE, - payload: null, - } + return {type: RESET_MOUNTS_STATE, payload: null,} }; export const SET_ALLOW_MOUNT = 'mounts/setAllowMount'; -export const setAllowMount = (provider, allow) => { - return { - type: SET_ALLOW_MOUNT, - payload: { - provider, - allow - } +export const setAllowMount = + (provider, + allow) => { + return {type: SET_ALLOW_MOUNT, payload: {provider, allow}}; }; -}; export const SET_AUTO_MOUNT_PROCESSED = 'mounts/setAutoMountProcessed'; export const setAutoMountProcessed = (provider, processed) => { - return { - type: SET_AUTO_MOUNT_PROCESSED, - payload: { - provider, - processed - } - }; + return {type: SET_AUTO_MOUNT_PROCESSED, payload: {provider, processed}}; }; export const setBusy = createAction('mounts/setBusy'); export const SET_MOUNT_STATE = 'mounts/setMountState'; -export const setMountState = (provider, state) => { - return { - type: SET_MOUNT_STATE, - payload: { - provider, - state - } +export const setMountState = + (provider, + state) => { + return {type: SET_MOUNT_STATE, payload: {provider, state}}; }; -}; export const SET_MOUNTED = 'mounts/setMounted'; -export const setMounted = (provider, mounted) => { - return { - type: SET_MOUNTED, - payload: { - provider, - mounted - } +export const setMounted = + (provider, + mounted) => { + return {type: SET_MOUNTED, payload: {provider, mounted}}; }; -}; export const SET_PROVIDER_STATE = 'mounts/setProviderState'; export const setProviderState = (provider, state) => { - return { - type: SET_PROVIDER_STATE, - payload: { - provider, - state - } - } + return {type: SET_PROVIDER_STATE, payload: {provider, state}} }; export const unmountAll = completedCallback => { diff --git a/src/redux/reducers/mount_reducer.js b/src/redux/reducers/mount_reducer.js index 10bb0a1..a55d692 100644 --- a/src/redux/reducers/mount_reducer.js +++ b/src/redux/reducers/mount_reducer.js @@ -1,24 +1,28 @@ -import * as Constants from '../../constants'; import {createReducer} from '@reduxjs/toolkit'; + +import * as Constants from '../../constants'; import { addRemoteMount2, + addS3Mount2, DISPLAY_CONFIGURATION, removeRemoteMount3, RESET_MOUNTS_STATE, SET_ALLOW_MOUNT, SET_AUTO_MOUNT_PROCESSED, - setBusy, SET_MOUNT_STATE, SET_MOUNTED, - SET_PROVIDER_STATE + SET_PROVIDER_STATE, + setBusy } from '../actions/mount_actions'; export const createMountReducer = state => { let providerList = [ ...Constants.PROVIDER_LIST, - ...(state.RemoteMounts||[]), + ...(state.RemoteMounts || []), + ...(state.S3Mounts || []), ]; - const providerState = providerList.map(provider=> { + const providerState = providerList + .map(provider => { return { [provider]: { AutoMount: false, @@ -26,14 +30,13 @@ export const createMountReducer = state => { MountLocation: '', } } - }).reduce((map, obj) => { - return { - ...map, - ...obj - } + }) + .reduce((map, obj) => { + return {...map, ...obj} }); - const mountState = providerList.map(provider => { + const mountState = providerList + .map(provider => { return { [provider]: { AllowMount: false, @@ -41,154 +44,172 @@ export const createMountReducer = state => { Mounted: false, } } - }).reduce((map, obj) => { - return { - ...map, - ...obj - } + }) + .reduce((map, obj) => { + return {...map, ...obj} }); - const autoMountProcessed = providerList.map(provider => { - return { - [provider]: false, - } - }).reduce((map, obj) => { - return { - ...map, - ...obj - } - }); + const autoMountProcessed = + providerList.map(provider => { + return {[provider]: false,} + }) + .reduce((map, obj) => { + return {...map, ...obj} + }); - return createReducer({ - AutoMountProcessed: autoMountProcessed, - DisplayConfiguration: null, - DisplayRemoteConfiguration: false, - MountsBusy: false, - MountState: mountState, - ProviderState: providerState, - RemoteMounts: state.RemoteMounts ? state.RemoteMounts : [], - }, { - [addRemoteMount2]: (state, action) => { - let mountState = {...state.MountState}; - mountState[action.payload] = { - AllowMount: false, - DriveLetters: [], - Mounted: false, - }; - - let providerState = {...state.ProviderState}; - providerState[action.payload] = { - AutoMount: false, - AutoRestart: false, - MountLocation: '', - }; - - let autoMountProcessed = {...state.AutoMountProcessed}; - autoMountProcessed[action.payload] = true; - - return { - ...state, - AutoMountProcessed: autoMountProcessed, - MountState: mountState, - ProviderState: providerState, - RemoteMounts: [...state.RemoteMounts, action.payload], - } + return createReducer( + { + AutoMountProcessed: autoMountProcessed, + DisplayConfiguration: null, + DisplayRemoteConfiguration: false, + DisplayS3Configuration: false, + MountsBusy: false, + MountState: mountState, + ProviderState: providerState, + RemoteMounts: state.RemoteMounts ? state.RemoteMounts : [], + S3Mounts: state.S3Mounts ? state.S3Mounts : [], }, - [DISPLAY_CONFIGURATION]: (state, action) => { - return { - ...state, - DisplayConfiguration: action.payload.provider, - DisplayRemoteConfiguration: action.payload.remote, - }; - }, - [removeRemoteMount3]: (state, action) => { - let mountState = {...state.MountState}; - delete mountState[action.payload]; + { + [addRemoteMount2]: (state, action) => { + let mountState = {...state.MountState}; + mountState[action.payload] = { + AllowMount: false, + DriveLetters: [], + Mounted: false, + }; - let providerState = {...state.ProviderState}; - delete providerState[action.payload]; + let providerState = {...state.ProviderState}; + providerState[action.payload] = { + AutoMount: false, + AutoRestart: false, + MountLocation: '', + }; - let autoMountProcessed = {...state.AutoMountProcessed}; - delete autoMountProcessed[action.payload]; + let autoMountProcessed = {...state.AutoMountProcessed}; + autoMountProcessed[action.payload] = true; - const remoteMounts = state.RemoteMounts.filter(i => i !== action.payload); - return { - ...state, - AutoMountProcessed: autoMountProcessed, - MountState: mountState, - ProviderState: providerState, - RemoteMounts: remoteMounts, - }; - }, - [RESET_MOUNTS_STATE]: (state, action) => { - return { - ...state, - MountsBusy: false, - MountState: mountState, - } - }, - [SET_AUTO_MOUNT_PROCESSED]: (state, action) => { - return { - ...state, - AutoMountProcessed: { - ...state.AutoMountProcessed, - [action.payload.provider]: action.payload.processed, + return { + ...state, AutoMountProcessed: autoMountProcessed, + MountState: mountState, ProviderState: providerState, + RemoteMounts: [...state.RemoteMounts, action.payload], } - }; - }, - [SET_ALLOW_MOUNT]: (state, action) => { - return { - ...state, - MountState: { - ...state.MountState, - [action.payload.provider]: { - ...state.MountState[action.payload.provider], - AllowMount: action.payload.allow, + }, + [addS3Mount2]: (state, action) => { + let mountState = {...state.MountState}; + mountState[action.payload] = { + AllowMount: false, + DriveLetters: [], + Mounted: false, + }; + + let providerState = {...state.ProviderState}; + providerState[action.payload] = { + AutoMount: false, + AutoRestart: false, + MountLocation: '', + }; + + let autoMountProcessed = {...state.AutoMountProcessed}; + autoMountProcessed[action.payload] = true; + + return { + ...state, AutoMountProcessed: autoMountProcessed, + MountState: mountState, ProviderState: providerState, + S3Mounts: [...state.S3Mounts, action.payload], + } + }, + [DISPLAY_CONFIGURATION]: (state, action) => { + return { + ...state, + DisplayConfiguration: action.payload.provider, + DisplayRemoteConfiguration: action.payload.remote, + DisplayS3Configuration: action.payload.s3, + }; + }, + [removeRemoteMount3]: (state, action) => { + let mountState = {...state.MountState}; + delete mountState[action.payload]; + + let providerState = {...state.ProviderState}; + delete providerState[action.payload]; + + let autoMountProcessed = {...state.AutoMountProcessed}; + delete autoMountProcessed[action.payload]; + + const remoteMounts = + state.RemoteMounts.filter(i => i !== action.payload); + return { + ...state, + AutoMountProcessed: autoMountProcessed, + MountState: mountState, + ProviderState: providerState, + RemoteMounts: remoteMounts, + }; + }, + [RESET_MOUNTS_STATE]: (state, action) => { + return {...state, MountsBusy: false, MountState: mountState,} + }, + [SET_AUTO_MOUNT_PROCESSED]: (state, action) => { + return { + ...state, + AutoMountProcessed: { + ...state.AutoMountProcessed, + [action.payload.provider]: action.payload.processed, } - } - }; - }, - [setBusy]: (state, action) => { - return { - ...state, - MountsBusy: action.payload - }; - }, - [SET_MOUNT_STATE]: (state, action) => { - return { - ...state, - MountState: { - ...state.MountState, - [action.payload.provider]: { - ...state.MountState[action.payload.provider], - ...action.payload.state - }, - } - }; - }, - [SET_MOUNTED]: (state, action) => { - return { - ...state, - MountState: { - ...state.MountState, - [action.payload.provider]: { - ...state.MountState[action.payload.provider], - Mounted: action.payload.mounted, + }; + }, + [SET_ALLOW_MOUNT]: (state, action) => { + return { + ...state, + MountState: { + ...state.MountState, + [action.payload.provider]: { + ...state.MountState[action.payload.provider], + AllowMount: action.payload.allow, + } } - } - }; - }, - [SET_PROVIDER_STATE]: (state, action) => { - return { - ...state, - ProviderState: { - ...state.ProviderState, - [action.payload.provider]: { - ...state.ProviderState[action.payload.provider], - ...action.payload.state - }, - } - }; - } - }); + }; + }, + [setBusy]: + (state, + action) => { + return {...state, MountsBusy: action.payload}; + }, + [SET_MOUNT_STATE]: (state, action) => { + return { + ...state, + MountState: { + ...state.MountState, + [action.payload.provider]: { + ...state.MountState[action.payload.provider], + ...action.payload.state + }, + } + }; + }, + [SET_MOUNTED]: (state, action) => { + return { + ...state, + MountState: { + ...state.MountState, + [action.payload.provider]: { + ...state.MountState[action.payload.provider], + Mounted: action.payload.mounted, + } + } + }; + }, + [SET_PROVIDER_STATE]: (state, action) => { + return { + ...state, + ProviderState: { + ...state.ProviderState, + [action.payload.provider]: { + ...state.ProviderState[action.payload.provider], + ...action.payload.state + }, + } + }; + } + }); }; diff --git a/src/renderer/ipc/ConfigIPC.js b/src/renderer/ipc/ConfigIPC.js index a609eda..8e4796a 100644 --- a/src/renderer/ipc/ConfigIPC.js +++ b/src/renderer/ipc/ConfigIPC.js @@ -4,7 +4,7 @@ const helpers = require('../../helpers'); const addListeners = (ipcMain, {standardIPCReply}) => { ipcMain.on(Constants.IPC_Get_Config, (event, data) => { helpers - .getConfig(data.Version, data.Provider, data.Remote) + .getConfig(data.Version, data.Provider, data.Remote, data.S3) .then((data) => { if (data.Code === 0) { standardIPCReply(event, Constants.IPC_Get_Config_Reply, { @@ -21,7 +21,7 @@ const addListeners = (ipcMain, {standardIPCReply}) => { ipcMain.on(Constants.IPC_Get_Config_Template, (event, data) => { helpers - .getConfigTemplate(data.Version, data.Provider, data.Remote) + .getConfigTemplate(data.Version, data.Provider, data.Remote, data.S3) .then((data) => { standardIPCReply(event, Constants.IPC_Get_Config_Template_Reply, { Template: data, @@ -36,7 +36,7 @@ const addListeners = (ipcMain, {standardIPCReply}) => { const setConfigValue = (i) => { if (i < data.Items.length) { helpers - .setConfigValue(data.Items[i].Name, data.Items[i].Value, data.Provider, data.Remote, data.Version) + .setConfigValue(data.Items[i].Name, data.Items[i].Value, data.Provider, data.Remote, data.S3, data.Version) .then(() => { setConfigValue(++i); }) diff --git a/src/renderer/ipc/MountsIPC.js b/src/renderer/ipc/MountsIPC.js index 1767bc6..4eedbea 100644 --- a/src/renderer/ipc/MountsIPC.js +++ b/src/renderer/ipc/MountsIPC.js @@ -55,7 +55,7 @@ const unmountAllDrives = () => { // Unmount all items for (const i in mountedLocations) { const data = mountedData[mountedLocations[i]]; - helpers.stopMountProcessSync(data.Version, data.Provider, data.Remote); + helpers.stopMountProcessSync(data.Version, data.Provider, data.Remote, data.S3); } mountedLocations = []; @@ -206,6 +206,7 @@ const addListeners = (ipcMain, {setTrayImage, standardIPCReply}) => { mountedData[data.Location] = { Provider: data.Provider, Remote: data.Remote, + S3: data.S3, Version: data.Version, }; const errorHandler = (pid, error) => { @@ -219,16 +220,18 @@ const addListeners = (ipcMain, {setTrayImage, standardIPCReply}) => { Location: data.Location, Provider: data.Provider, Remote: data.Remote, + S3: data.S3, }, error || Error(data.Provider + ' Unmounted')); }; helpers - .executeMount(data.Version, data.Provider, data.Remote, data.Location, (error, pid) => { + .executeMount(data.Version, data.Provider, data.Remote, data.S3, data.Location, (error, pid) => { errorHandler(pid, error); }) .then(() => { standardIPCReply(event, Constants.IPC_Mount_Drive_Reply, { Provider: data.Provider, Remote: data.Remote, + S3: data.S3, }); }) .catch(error => { @@ -259,7 +262,7 @@ const addListeners = (ipcMain, {setTrayImage, standardIPCReply}) => { expectedUnmount[data.Provider] = true; helpers - .stopMountProcess(data.Version, data.Provider, data.Remote) + .stopMountProcess(data.Version, data.Provider, data.Remote, data.S3) .then(result => { console.log(result); })