diff --git a/packages/api/src/controllers/auth.js b/packages/api/src/controllers/auth.js index fbaa74f3d..4f614f065 100644 --- a/packages/api/src/controllers/auth.js +++ b/packages/api/src/controllers/auth.js @@ -140,8 +140,8 @@ module.exports = { createCloudLoginSession_meta: true, async createCloudLoginSession({ client }) { const res = await createDbGateIdentitySession(client); - startCloudTokenChecking(res.sid, token => { - socket.emit('got-cloud-token', { token }); + startCloudTokenChecking(res.sid, tokenHolder => { + socket.emit('got-cloud-token', tokenHolder); }); return res; }, diff --git a/packages/api/src/controllers/cloud.js b/packages/api/src/controllers/cloud.js index c05c3863a..9e4483eec 100644 --- a/packages/api/src/controllers/cloud.js +++ b/packages/api/src/controllers/cloud.js @@ -6,6 +6,7 @@ const { callCloudApiPost, getCloudFolderEncryptor, getCloudContent, + putCloudContent, } = require('../utility/cloudIntf'); const connections = require('./connections'); const socket = require('../utility/socket'); @@ -55,7 +56,7 @@ module.exports = { putContent_meta: true, async putContent({ folid, cntid, content, name, type }) { - await callCloudApiPost(`put-content`, { folid, cntid, content, name, type }); + putCloudContent(folid, cntid, content, name, type); socket.emitChanged('cloud-content-changed'); return { status: 'ok', diff --git a/packages/api/src/utility/cloudIntf.js b/packages/api/src/utility/cloudIntf.js index 11ae9a11d..7b36307bc 100644 --- a/packages/api/src/utility/cloudIntf.js +++ b/packages/api/src/utility/cloudIntf.js @@ -64,7 +64,7 @@ function startCloudTokenChecking(sid, callback) { if (resp.data.status == 'ok') { clearInterval(interval); - callback(resp.data.token); + callback(resp.data); } } catch (err) { logger.error(extractErrorLogData(err), 'Error checking cloud token'); @@ -123,17 +123,26 @@ async function collectCloudFilesSearchTags() { return res; } -async function getCloudSigninHeaders() { +async function getCloudSigninHolder() { const settingsValue = await config.getSettings(); - const value = settingsValue['cloudSigninToken']; - if (value) { + const holder = settingsValue['cloudSigninTokenHolder']; + return holder; +} + +async function getCloudSigninHeaders(holder = null) { + if (!holder) { + holder = await getCloudSigninHolder(); + } + if (holder) { return { - 'x-cloud-login': value, + 'x-cloud-login': holder.token, }; } return null; } +let cloudFilesWereUpdated = false; + async function updateCloudFiles() { let lastCloudFilesTags; try { @@ -151,7 +160,9 @@ async function updateCloudFiles() { logger.info({ tags, lastCheckedTm }, 'Downloading cloud files'); const resp = await axios.default.get( - `${DBGATE_CLOUD_URL}/public-cloud-updates?lastCheckedTm=${lastCheckedTm}&tags=${tags}`, + `${DBGATE_CLOUD_URL}/public-cloud-updates?lastCheckedTm=${lastCheckedTm}&tags=${tags}&isRefresh=${ + cloudFilesWereUpdated ? 1 : 0 + }`, { headers: { ...getLicenseHttpHeaders(), @@ -159,6 +170,7 @@ async function updateCloudFiles() { }, } ); + cloudFilesWereUpdated = true; logger.info(`Downloaded ${resp.data.length} cloud files`); @@ -210,26 +222,33 @@ async function refreshPublicFiles() { } } -async function callCloudApiGet(endpoint) { - const signinHeaders = await getCloudSigninHeaders(); - if (!signinHeaders) { +async function callCloudApiGet(endpoint, signinHolder = null, additionalHeaders = {}) { + if (!signinHolder) { + signinHolder = await getCloudSigninHolder(); + } + if (!signinHolder) { return null; } + const signinHeaders = await getCloudSigninHeaders(signinHolder); const resp = await axios.default.get(`${DBGATE_CLOUD_URL}/${endpoint}`, { headers: { ...getLicenseHttpHeaders(), ...signinHeaders, + ...additionalHeaders, }, }); return resp.data; } -async function callCloudApiPost(endpoint, body) { - const signinHeaders = await getCloudSigninHeaders(); - if (!signinHeaders) { +async function callCloudApiPost(endpoint, body, signinHolder = null) { + if (!signinHolder) { + signinHolder = await getCloudSigninHolder(); + } + if (!signinHolder) { return null; } + const signinHeaders = await getCloudSigninHeaders(signinHolder); const resp = await axios.default.post(`${DBGATE_CLOUD_URL}/${endpoint}`, body, { headers: { @@ -249,8 +268,45 @@ async function getCloudFolderEncryptor(folid) { } async function getCloudContent(folid, cntid) { - const { content, name, type } = await callCloudApiGet(`content/${folid}/${cntid}`); - return { content, name, type }; + const signinHolder = await getCloudSigninHolder(); + if (!signinHolder) { + throw new Error('No signed in'); + } + + const encryptor = simpleEncryptor.createEncryptor(signinHolder.encryptionKey); + + const { content, name, type } = await callCloudApiGet(`content/${folid}/${cntid}`, signinHolder, { + 'x-kehid': signinHolder.kehid, + }); + + return { + content: encryptor.decrypt(content), + name, + type, + }; +} + +async function putCloudContent(folid, cntid, content, name, type) { + const signinHolder = await getCloudSigninHolder(); + if (!signinHolder) { + throw new Error('No signed in'); + } + + const encryptor = simpleEncryptor.createEncryptor(signinHolder.encryptionKey); + + await callCloudApiPost( + `put-content`, + { + folid, + cntid, + name, + type, + kehid: signinHolder.kehid, + content: encryptor.encrypt(content), + }, + signinHolder + ); + socket.emitChanged('cloud-content-changed'); } const cloudConnectionCache = {}; @@ -278,4 +334,5 @@ module.exports = { getCloudFolderEncryptor, getCloudContent, loadCachedCloudConnection, + putCloudContent, }; diff --git a/packages/web/src/appobj/ConnectionAppObject.svelte b/packages/web/src/appobj/ConnectionAppObject.svelte index d6fedd9ab..e46f69f3d 100644 --- a/packages/web/src/appobj/ConnectionAppObject.svelte +++ b/packages/web/src/appobj/ConnectionAppObject.svelte @@ -108,7 +108,7 @@ import _ from 'lodash'; import AppObjectCore from './AppObjectCore.svelte'; import { - cloudSigninToken, + cloudSigninTokenHolder, currentDatabase, DEFAULT_CONNECTION_SEARCH_SETTINGS, expandedConnections, @@ -334,7 +334,7 @@ onClick: handleDuplicate, }, !$openedConnections.includes(data._id) && - $cloudSigninToken && + $cloudSigninTokenHolder && passProps?.cloudContentList?.length > 0 && { text: _t('connection.moveToCloudFolder', { defaultMessage: 'Move to cloud folder' }), submenu: passProps?.cloudContentList?.map(fld => ({ diff --git a/packages/web/src/commands/stdCommands.ts b/packages/web/src/commands/stdCommands.ts index d1138f079..2432d0fcb 100644 --- a/packages/web/src/commands/stdCommands.ts +++ b/packages/web/src/commands/stdCommands.ts @@ -1,5 +1,5 @@ import { - cloudSigninToken, + cloudSigninTokenHolder, currentDatabase, currentTheme, emptyConnectionGroupNames, @@ -668,7 +668,7 @@ registerCommand({ category: 'Cloud', name: 'Logout', onClick: () => { - cloudSigninToken.set(null); + cloudSigninTokenHolder.set(null); }, }); diff --git a/packages/web/src/stores.ts b/packages/web/src/stores.ts index 61b827109..1de2cdc71 100644 --- a/packages/web/src/stores.ts +++ b/packages/web/src/stores.ts @@ -182,14 +182,10 @@ export const focusedConnectionOrDatabase = writable<{ conid: string; database?: export const focusedTreeDbKey = writable<{ key: string; root: string; type: string; text: string }>(null); -export const cloudSigninToken = writableSettingsValue(null, 'cloudSigninToken'); +export const cloudSigninTokenHolder = writableSettingsValue(null, 'cloudSigninTokenHolder'); export const cloudConnectionsStore = writable({}); -// export const cloudSigninToken = getElectron() -// ? writableSettingsValue(null, 'cloudSigninToken') -// : writableWithStorage(null, 'cloudSigninToken'); - export const DEFAULT_OBJECT_SEARCH_SETTINGS = { pureName: true, schemaName: false, diff --git a/packages/web/src/utility/api.ts b/packages/web/src/utility/api.ts index 0314cb047..29cfb5c2e 100644 --- a/packages/web/src/utility/api.ts +++ b/packages/web/src/utility/api.ts @@ -14,7 +14,7 @@ import { batchDispatchCacheTriggers, dispatchCacheChange } from './cache'; import { isAdminPage, isOneOfPage } from './pageDefs'; import { openWebLink } from './simpleTools'; import { serializeJsTypesReplacer } from 'dbgate-tools'; -import { cloudSigninToken } from '../stores'; +import { cloudSigninTokenHolder } from '../stores'; export const strmid = uuidv1(); @@ -281,8 +281,9 @@ export function installNewVolatileConnectionListener() { } export function installNewCloudTokenListener() { - apiOn('got-cloud-token', async ({ token }) => { - cloudSigninToken.set(token); + apiOn('got-cloud-token', async tokenHolder => { + console.log('HOLDER', tokenHolder); + cloudSigninTokenHolder.set(tokenHolder); }); } diff --git a/packages/web/src/widgets/PrivateCloudWidget.svelte b/packages/web/src/widgets/PrivateCloudWidget.svelte index 623bbcdc6..bf096a1f2 100644 --- a/packages/web/src/widgets/PrivateCloudWidget.svelte +++ b/packages/web/src/widgets/PrivateCloudWidget.svelte @@ -16,7 +16,7 @@ import { apiCall } from '../utility/api'; import { cloudConnectionsStore, - cloudSigninToken, + cloudSigninTokenHolder, currentDatabase, expandedConnections, openedConnections, @@ -82,7 +82,7 @@ name="privateCloud" height="50%" storageName="privateCloudItems" - skip={!$cloudSigninToken} + skip={!$cloudSigninTokenHolder} > diff --git a/packages/web/src/widgets/WidgetIconPanel.svelte b/packages/web/src/widgets/WidgetIconPanel.svelte index ecc9dd1fc..b0d25f2b6 100644 --- a/packages/web/src/widgets/WidgetIconPanel.svelte +++ b/packages/web/src/widgets/WidgetIconPanel.svelte @@ -9,7 +9,7 @@ visibleHamburgerMenuWidget, lockedDatabaseMode, getCurrentConfig, - cloudSigninToken, + cloudSigninTokenHolder, } from '../stores'; import mainMenuDefinition from '../../../../app/src/mainMenuDefinition'; import hasPermission from '../utility/hasPermission'; @@ -149,7 +149,7 @@ {#each widgets .filter(x => x && hasPermission(`widgets/${x.name}`)) .filter(x => !x.isPremiumPromo || !isProApp()) - .filter(x => x.name != 'cloud-private' || $cloudSigninToken) as item} + .filter(x => x.name != 'cloud-private' || $cloudSigninTokenHolder) as item}
--> - {#if $cloudSigninToken} + {#if $cloudSigninTokenHolder}