diff --git a/CHANGELOG.md b/CHANGELOG.md index e8c820e4e..b89addefc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - [Backup NG form] Ability to edit a schedule's name [#2711](https://github.com/vatesfr/xen-orchestra/issues/2711) [#3071](https://github.com/vatesfr/xen-orchestra/issues/3071) (PR [#3143](https://github.com/vatesfr/xen-orchestra/pull/3143)) - [Remotes] Ability to change the type of a remote [#2423](https://github.com/vatesfr/xen-orchestra/issues/2423) (PR [#3207](https://github.com/vatesfr/xen-orchestra/pull/3207)) - [Backup NG new] Ability to set a job's timeout [#2978](https://github.com/vatesfr/xen-orchestra/issues/2978) (PR [#3222](https://github.com/vatesfr/xen-orchestra/pull/3222)) +- [Remotes] Ability to edit/delete a remote with an invalid URL [#3182](https://github.com/vatesfr/xen-orchestra/issues/3182) (PR [#3226](https://github.com/vatesfr/xen-orchestra/pull/3226)) ### Bug fixes @@ -20,6 +21,7 @@ ### Released packages +- xo-remote-parser v0.5.0 - complex-matcher v0.4.0 - xo-server-backup-reports v0.12.3 - xo-server v5.23.0 diff --git a/packages/xo-remote-parser/src/index.js b/packages/xo-remote-parser/src/index.js index 90fdcc2ea..eef040d81 100644 --- a/packages/xo-remote-parser/src/index.js +++ b/packages/xo-remote-parser/src/index.js @@ -19,7 +19,14 @@ export const parse = string => { object.path = `/${trimStart(rest, '/')}` // the leading slash has been forgotten on client side first implementation } else if (type === 'nfs') { object.type = 'nfs' - const [, host, port, path] = NFS_RE.exec(rest) + let host, port, path + // Some users have a remote with a colon in the URL, which breaks the parsing since this commit: https://github.com/vatesfr/xen-orchestra/commit/fb1bf6a1e748b457f2d2b89ba02fa104554c03df + try { + ;[, host, port, path] = NFS_RE.exec(rest) + } catch (err) { + ;[host, path] = rest.split(':') + object.invalidUrl = true + } object.host = host object.port = port object.path = `/${trimStart(path, '/')}` // takes care of a missing leading slash coming from previous version format diff --git a/packages/xo-web/src/common/intl/messages.js b/packages/xo-web/src/common/intl/messages.js index 06ddc67fd..5265b6672 100644 --- a/packages/xo-web/src/common/intl/messages.js +++ b/packages/xo-web/src/common/intl/messages.js @@ -1295,6 +1295,8 @@ const messages = { 'Only the files of Delta Backup which are not on a SMB remote can be restored', remoteEnabled: 'Enabled', remoteError: 'Error', + remoteErrorMessage: + 'The URL ({url}) is invalid (colon in path). Click this button to change the URL to {newUrl}.', noBackup: 'No backup available', backupVmNameColumn: 'VM Name', backupVmDescriptionColumn: 'VM Description', diff --git a/packages/xo-web/src/common/select-objects.js b/packages/xo-web/src/common/select-objects.js index 086302c1d..63d0e2db8 100644 --- a/packages/xo-web/src/common/select-objects.js +++ b/packages/xo-web/src/common/select-objects.js @@ -705,14 +705,11 @@ export const SelectRemote = makeSubscriptionSelect( subscriber => { const unsubscribeRemotes = subscribeRemotes(remotes => { const xoObjects = groupBy( - map(sortBy(remotes, 'name'), remote => { - try { - remote = { ...remote, ...parseRemote(remote.url) } - return { id: remote.id, type: 'remote', value: remote } - } catch (err) { - console.error('Remote parsing error:', remote, '\n', err) - } - }).filter(r => r !== undefined), + map(sortBy(remotes, 'name'), remote => ({ + id: remote.id, + type: 'remote', + value: { ...remote, ...parseRemote(remote.url) }, + })).filter(r => !r.value.invalid), remote => remote.value.type ) diff --git a/packages/xo-web/src/xo-app/settings/remotes/index.js b/packages/xo-web/src/xo-app/settings/remotes/index.js index c980b50f8..f073764e0 100644 --- a/packages/xo-web/src/xo-app/settings/remotes/index.js +++ b/packages/xo-web/src/xo-app/settings/remotes/index.js @@ -1,4 +1,5 @@ import _, { messages } from 'intl' +import ActionButton from 'action-button' import Icon from 'icon' import React from 'react' import SortedTable from 'sorted-table' @@ -71,6 +72,7 @@ const COLUMN_STATE = { name: _('remoteState'), } +const fixRemoteUrl = remote => editRemote(remote, { url: format(remote) }) const COLUMNS_LOCAL_REMOTE = [ COLUMN_NAME, { @@ -116,7 +118,20 @@ const COLUMNS_NFS_REMOTE = [ onChange={_changeUrlElement} placeholder={formatMessage(messages.remoteNfsPlaceHolderPath)} value={remote.path} - /> + />{' '} + {remote.invalidUrl && ( + + )} ), @@ -247,16 +262,10 @@ export default [ subscribeRemotes(remotes => { cb( groupBy( - map(remotes, remote => { - try { - return { - ...remote, - ...parse(remote.url), - } - } catch (err) { - console.error('Remote parsing error:', remote, '\n', err) - } - }).filter(r => r !== undefined), + map(remotes, remote => ({ + ...parse(remote.url), + ...remote, + })), 'type' ) )