|
| 1 | +/** |
| 2 | + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors |
| 3 | + * SPDX-FileCopyrightText: 2014-2016 ownCloud, Inc. |
| 4 | + * SPDX-License-Identifier: AGPL-3.0-or-later |
| 5 | + */ |
| 6 | +import { loadState } from '@nextcloud/initial-state' |
| 7 | +import { generateUrl } from '@nextcloud/router' |
| 8 | + |
| 9 | +window.OCA.Sharing = window.OCA.Sharing || {} |
| 10 | + |
| 11 | +/** |
| 12 | + * Shows "add external share" dialog. |
| 13 | + * |
| 14 | + * @param {object} share the share |
| 15 | + * @param {string} share.remote remote server URL |
| 16 | + * @param {string} share.owner owner name |
| 17 | + * @param {string} share.name name of the shared folder |
| 18 | + * @param {string} share.token authentication token |
| 19 | + * @param {boolean} passwordProtected true if the share is password protected |
| 20 | + * @param {Function} callback the callback |
| 21 | + */ |
| 22 | +window.OCA.Sharing.showAddExternalDialog = function(share, passwordProtected, callback) { |
| 23 | + const remote = share.remote |
| 24 | + const owner = share.ownerDisplayName || share.owner |
| 25 | + const name = share.name |
| 26 | + |
| 27 | + // Clean up the remote URL for display |
| 28 | + const remoteClean = remote |
| 29 | + .replace(/^https?:\/\//, '') // remove http:// or https:// |
| 30 | + .replace(/\/$/, '') // remove trailing slash |
| 31 | + |
| 32 | + if (!passwordProtected) { |
| 33 | + window.OC.dialogs.confirm( |
| 34 | + t( |
| 35 | + 'files_sharing', |
| 36 | + 'Do you want to add the remote share {name} from {owner}@{remote}?', |
| 37 | + { name, owner, remote: remoteClean }, |
| 38 | + ), |
| 39 | + t('files_sharing', 'Remote share'), |
| 40 | + function(result) { |
| 41 | + callback(result, share) |
| 42 | + }, |
| 43 | + true, |
| 44 | + ).then(this._adjustDialog) |
| 45 | + } else { |
| 46 | + window.OC.dialogs.prompt( |
| 47 | + t( |
| 48 | + 'files_sharing', |
| 49 | + 'Do you want to add the remote share {name} from {owner}@{remote}?', |
| 50 | + { name, owner, remote: remoteClean }, |
| 51 | + ), |
| 52 | + t('files_sharing', 'Remote share'), |
| 53 | + function(result, password) { |
| 54 | + share.password = password |
| 55 | + callback(result, share) |
| 56 | + }, |
| 57 | + true, |
| 58 | + t('files_sharing', 'Remote share password'), |
| 59 | + true, |
| 60 | + ).then(this._adjustDialog) |
| 61 | + } |
| 62 | +} |
| 63 | + |
| 64 | +window.OCA.Sharing._adjustDialog = function() { |
| 65 | + const $dialog = $('.oc-dialog:visible') |
| 66 | + const $buttons = $dialog.find('button') |
| 67 | + // hack the buttons |
| 68 | + $dialog.find('.ui-icon').remove() |
| 69 | + $buttons.eq(1).text(t('core', 'Cancel')) |
| 70 | + $buttons.eq(2).text(t('files_sharing', 'Add remote share')) |
| 71 | +} |
| 72 | + |
| 73 | +const reloadFilesList = function() { |
| 74 | + if (!window?.OCP?.Files?.Router?.goToRoute) { |
| 75 | + // No router, just reload the page |
| 76 | + window.location.reload() |
| 77 | + return |
| 78 | + } |
| 79 | + |
| 80 | + // Let's redirect to the root as any accepted share would be there |
| 81 | + window.OCP.Files.Router.goToRoute( |
| 82 | + null, |
| 83 | + { ...window.OCP.Files.Router.params, fileid: undefined }, |
| 84 | + { ...window.OCP.Files.Router.query, dir: '/', openfile: undefined }, |
| 85 | + ) |
| 86 | +} |
| 87 | + |
| 88 | +/** |
| 89 | + * Process incoming remote share that might have been passed |
| 90 | + * through the URL |
| 91 | + */ |
| 92 | +const processIncomingShareFromUrl = function() { |
| 93 | + const params = window.OC.Util.History.parseUrlQuery() |
| 94 | + |
| 95 | + // manually add server-to-server share |
| 96 | + if (params.remote && params.token && params.name) { |
| 97 | + |
| 98 | + const callbackAddShare = function(result, share) { |
| 99 | + const password = share.password || '' |
| 100 | + if (result) { |
| 101 | + $.post( |
| 102 | + generateUrl('apps/federatedfilesharing/askForFederatedShare'), |
| 103 | + { |
| 104 | + remote: share.remote, |
| 105 | + token: share.token, |
| 106 | + owner: share.owner, |
| 107 | + ownerDisplayName: share.ownerDisplayName || share.owner, |
| 108 | + name: share.name, |
| 109 | + password, |
| 110 | + }, |
| 111 | + ).done(function(data) { |
| 112 | + if (data.hasOwnProperty('legacyMount')) { |
| 113 | + reloadFilesList() |
| 114 | + } else { |
| 115 | + window.OC.Notification.showTemporary(data.message) |
| 116 | + } |
| 117 | + }).fail(function(data) { |
| 118 | + window.OC.Notification.showTemporary(JSON.parse(data.responseText).message) |
| 119 | + }) |
| 120 | + } |
| 121 | + } |
| 122 | + |
| 123 | + // clear hash, it is unlikely that it contain any extra parameters |
| 124 | + location.hash = '' |
| 125 | + params.passwordProtected = parseInt(params.protected, 10) === 1 |
| 126 | + window.OCA.Sharing.showAddExternalDialog( |
| 127 | + params, |
| 128 | + params.passwordProtected, |
| 129 | + callbackAddShare, |
| 130 | + ) |
| 131 | + } |
| 132 | +} |
| 133 | + |
| 134 | +/** |
| 135 | + * Retrieve a list of remote shares that need to be approved |
| 136 | + */ |
| 137 | +const processSharesToConfirm = function() { |
| 138 | + // check for new server-to-server shares which need to be approved |
| 139 | + $.get(generateUrl('/apps/files_sharing/api/externalShares'), {}, function(shares) { |
| 140 | + let index |
| 141 | + for (index = 0; index < shares.length; ++index) { |
| 142 | + window.OCA.Sharing.showAddExternalDialog( |
| 143 | + shares[index], |
| 144 | + false, |
| 145 | + function(result, share) { |
| 146 | + if (result) { |
| 147 | + // Accept |
| 148 | + $.post(generateUrl('/apps/files_sharing/api/externalShares'), { id: share.id }) |
| 149 | + .then(function() { |
| 150 | + reloadFilesList() |
| 151 | + }) |
| 152 | + } else { |
| 153 | + // Delete |
| 154 | + $.ajax({ |
| 155 | + url: generateUrl('/apps/files_sharing/api/externalShares/' + share.id), |
| 156 | + type: 'DELETE', |
| 157 | + }) |
| 158 | + } |
| 159 | + }, |
| 160 | + ) |
| 161 | + } |
| 162 | + }) |
| 163 | +} |
| 164 | + |
| 165 | +processIncomingShareFromUrl() |
| 166 | + |
| 167 | +if (loadState('federatedfilesharing', 'notificationsEnabled', true) !== true) { |
| 168 | + // No notification app, display the modal |
| 169 | + processSharesToConfirm() |
| 170 | +} |
| 171 | + |
| 172 | +$('body').on('window.OCA.Notification.Action', function(e) { |
| 173 | + if (e.notification.app === 'files_sharing' && e.notification.object_type === 'remote_share' && e.action.type === 'POST') { |
| 174 | + // User accepted a remote share reload |
| 175 | + reloadFilesList() |
| 176 | + } |
| 177 | +}) |
0 commit comments