diff --git a/packages/api/src/controllers/cloud.js b/packages/api/src/controllers/cloud.js index 9acbc18c8..a4b6a20ea 100644 --- a/packages/api/src/controllers/cloud.js +++ b/packages/api/src/controllers/cloud.js @@ -70,7 +70,10 @@ module.exports = { grantFolder_meta: true, async grantFolder({ inviteLink }) { - const m = inviteLink.match(/^dbgate\:\/\/folder\/v1\/([a-zA-Z]+)\?mode=(read|write|admin)$/); + const m = inviteLink.match(/^dbgate\:\/\/folder\/v1\/([a-zA-Z0-9]+)\?mode=(read|write|admin)$/); + if (!m) { + throw new Error('Invalid invite link format'); + } const invite = m[1]; const mode = m[2]; @@ -93,6 +96,12 @@ module.exports = { return resp; }, + getInviteToken_meta: true, + async getInviteToken({ folid, role }) { + const resp = await callCloudApiGet(`invite-token/${folid}/${role}`); + return resp; + }, + refreshContent_meta: true, async refreshContent() { socket.emitChanged('cloud-content-changed'); diff --git a/packages/api/src/utility/cloudIntf.js b/packages/api/src/utility/cloudIntf.js index bf7fd12f1..d3b06231e 100644 --- a/packages/api/src/utility/cloudIntf.js +++ b/packages/api/src/utility/cloudIntf.js @@ -56,13 +56,15 @@ function startCloudTokenChecking(sid, callback) { } try { + // console.log(`Checking cloud token for session: ${DBGATE_IDENTITY_URL}/api/get-token/${sid}`); const resp = await axios.default.get(`${DBGATE_IDENTITY_URL}/api/get-token/${sid}`, { headers: { ...getLicenseHttpHeaders(), }, }); + // console.log('CHECK RESP:', resp.data); - if (resp.data.status == 'ok') { + if (resp.data.email) { clearInterval(interval); callback(resp.data); } diff --git a/packages/web/src/widgets/PrivateCloudWidget.svelte b/packages/web/src/widgets/PrivateCloudWidget.svelte index 4fb2c4519..0adc3a41b 100644 --- a/packages/web/src/widgets/PrivateCloudWidget.svelte +++ b/packages/web/src/widgets/PrivateCloudWidget.svelte @@ -31,6 +31,7 @@ import { showModal } from '../modals/modalTools'; import InputTextModal from '../modals/InputTextModal.svelte'; import ConfirmModal from '../modals/ConfirmModal.svelte'; + import { showSnackbarInfo } from '../utility/snackbar'; let publicFilter = ''; let cloudFilter = ''; @@ -56,9 +57,10 @@ return data; }); - $: contentGroupTitleMap = _.fromPairs(($cloudContentList || []).map(x => [x.folid, x.name])); + $: contentGroupMap = _.keyBy($cloudContentList || [], x => x.folid); // $: console.log('cloudContentFlat', cloudContentFlat); + // $: console.log('contentGroupMap', contentGroupMap); async function handleRefreshContent() { await apiCall('cloud/refresh-content'); @@ -115,7 +117,7 @@ function createGroupContextMenu(folder) { const handleRename = () => { showModal(InputTextModal, { - value: contentGroupTitleMap[folder], + value: contentGroupMap[folder]?.name, label: 'New folder name', header: 'Rename folder', onConfirm: async name => { @@ -129,7 +131,7 @@ const handleDelete = () => { showModal(ConfirmModal, { - message: `Really delete folder ${contentGroupTitleMap[folder]}? All folder content will be deleted!`, + message: `Really delete folder ${contentGroupMap[folder]?.name}? All folder content will be deleted!`, header: 'Delete folder', onConfirm: () => { apiCall('cloud/delete-folder', { @@ -139,9 +141,39 @@ }); }; + const handleCopyInviteLink = async role => { + const { inviteToken } = await apiCall(`cloud/get-invite-token`, { + folid: folder, + role, + }); + const inviteLink = `dbgate://folder/v1/${inviteToken}?mode=${role}`; + navigator.clipboard.writeText(inviteLink); + showSnackbarInfo(`Invite link (${role}) copied to clipboard`); + }; + return [ - { text: 'Rename', onClick: handleRename }, - { text: 'Delete', onClick: handleDelete }, + contentGroupMap[folder]?.role == 'admin' && [ + { text: 'Rename', onClick: handleRename }, + { text: 'Delete', onClick: handleDelete }, + ], + contentGroupMap[folder]?.role == 'admin' && + !contentGroupMap[folder]?.isPrivate && { + text: 'Copy invite link', + submenu: [ + { + text: 'Admin', + onClick: () => handleCopyInviteLink('admin'), + }, + { + text: 'Write', + onClick: () => handleCopyInviteLink('write'), + }, + { + text: 'Read', + onClick: () => handleCopyInviteLink('read'), + }, + ], + }, ]; } @@ -172,7 +204,7 @@ module={cloudContentAppObject} emptyGroupNames={emptyCloudContent} groupFunc={data => data.folid} - mapGroupTitle={folid => contentGroupTitleMap[folid]} + mapGroupTitle={folid => contentGroupMap[folid]?.name} filter={publicFilter} subItemsComponent={() => SubCloudItemsList} expandIconFunc={plusExpandIcon}