mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-05-03 21:03:59 +00:00
encrypting cloud content
This commit is contained in:
@@ -140,8 +140,8 @@ module.exports = {
|
|||||||
createCloudLoginSession_meta: true,
|
createCloudLoginSession_meta: true,
|
||||||
async createCloudLoginSession({ client }) {
|
async createCloudLoginSession({ client }) {
|
||||||
const res = await createDbGateIdentitySession(client);
|
const res = await createDbGateIdentitySession(client);
|
||||||
startCloudTokenChecking(res.sid, token => {
|
startCloudTokenChecking(res.sid, tokenHolder => {
|
||||||
socket.emit('got-cloud-token', { token });
|
socket.emit('got-cloud-token', tokenHolder);
|
||||||
});
|
});
|
||||||
return res;
|
return res;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ const {
|
|||||||
callCloudApiPost,
|
callCloudApiPost,
|
||||||
getCloudFolderEncryptor,
|
getCloudFolderEncryptor,
|
||||||
getCloudContent,
|
getCloudContent,
|
||||||
|
putCloudContent,
|
||||||
} = require('../utility/cloudIntf');
|
} = require('../utility/cloudIntf');
|
||||||
const connections = require('./connections');
|
const connections = require('./connections');
|
||||||
const socket = require('../utility/socket');
|
const socket = require('../utility/socket');
|
||||||
@@ -55,7 +56,7 @@ module.exports = {
|
|||||||
|
|
||||||
putContent_meta: true,
|
putContent_meta: true,
|
||||||
async putContent({ folid, cntid, content, name, type }) {
|
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');
|
socket.emitChanged('cloud-content-changed');
|
||||||
return {
|
return {
|
||||||
status: 'ok',
|
status: 'ok',
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ function startCloudTokenChecking(sid, callback) {
|
|||||||
|
|
||||||
if (resp.data.status == 'ok') {
|
if (resp.data.status == 'ok') {
|
||||||
clearInterval(interval);
|
clearInterval(interval);
|
||||||
callback(resp.data.token);
|
callback(resp.data);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error(extractErrorLogData(err), 'Error checking cloud token');
|
logger.error(extractErrorLogData(err), 'Error checking cloud token');
|
||||||
@@ -123,17 +123,26 @@ async function collectCloudFilesSearchTags() {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getCloudSigninHeaders() {
|
async function getCloudSigninHolder() {
|
||||||
const settingsValue = await config.getSettings();
|
const settingsValue = await config.getSettings();
|
||||||
const value = settingsValue['cloudSigninToken'];
|
const holder = settingsValue['cloudSigninTokenHolder'];
|
||||||
if (value) {
|
return holder;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getCloudSigninHeaders(holder = null) {
|
||||||
|
if (!holder) {
|
||||||
|
holder = await getCloudSigninHolder();
|
||||||
|
}
|
||||||
|
if (holder) {
|
||||||
return {
|
return {
|
||||||
'x-cloud-login': value,
|
'x-cloud-login': holder.token,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let cloudFilesWereUpdated = false;
|
||||||
|
|
||||||
async function updateCloudFiles() {
|
async function updateCloudFiles() {
|
||||||
let lastCloudFilesTags;
|
let lastCloudFilesTags;
|
||||||
try {
|
try {
|
||||||
@@ -151,7 +160,9 @@ async function updateCloudFiles() {
|
|||||||
logger.info({ tags, lastCheckedTm }, 'Downloading cloud files');
|
logger.info({ tags, lastCheckedTm }, 'Downloading cloud files');
|
||||||
|
|
||||||
const resp = await axios.default.get(
|
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: {
|
headers: {
|
||||||
...getLicenseHttpHeaders(),
|
...getLicenseHttpHeaders(),
|
||||||
@@ -159,6 +170,7 @@ async function updateCloudFiles() {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
cloudFilesWereUpdated = true;
|
||||||
|
|
||||||
logger.info(`Downloaded ${resp.data.length} cloud files`);
|
logger.info(`Downloaded ${resp.data.length} cloud files`);
|
||||||
|
|
||||||
@@ -210,26 +222,33 @@ async function refreshPublicFiles() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function callCloudApiGet(endpoint) {
|
async function callCloudApiGet(endpoint, signinHolder = null, additionalHeaders = {}) {
|
||||||
const signinHeaders = await getCloudSigninHeaders();
|
if (!signinHolder) {
|
||||||
if (!signinHeaders) {
|
signinHolder = await getCloudSigninHolder();
|
||||||
|
}
|
||||||
|
if (!signinHolder) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
const signinHeaders = await getCloudSigninHeaders(signinHolder);
|
||||||
|
|
||||||
const resp = await axios.default.get(`${DBGATE_CLOUD_URL}/${endpoint}`, {
|
const resp = await axios.default.get(`${DBGATE_CLOUD_URL}/${endpoint}`, {
|
||||||
headers: {
|
headers: {
|
||||||
...getLicenseHttpHeaders(),
|
...getLicenseHttpHeaders(),
|
||||||
...signinHeaders,
|
...signinHeaders,
|
||||||
|
...additionalHeaders,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return resp.data;
|
return resp.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function callCloudApiPost(endpoint, body) {
|
async function callCloudApiPost(endpoint, body, signinHolder = null) {
|
||||||
const signinHeaders = await getCloudSigninHeaders();
|
if (!signinHolder) {
|
||||||
if (!signinHeaders) {
|
signinHolder = await getCloudSigninHolder();
|
||||||
|
}
|
||||||
|
if (!signinHolder) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
const signinHeaders = await getCloudSigninHeaders(signinHolder);
|
||||||
|
|
||||||
const resp = await axios.default.post(`${DBGATE_CLOUD_URL}/${endpoint}`, body, {
|
const resp = await axios.default.post(`${DBGATE_CLOUD_URL}/${endpoint}`, body, {
|
||||||
headers: {
|
headers: {
|
||||||
@@ -249,8 +268,45 @@ async function getCloudFolderEncryptor(folid) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function getCloudContent(folid, cntid) {
|
async function getCloudContent(folid, cntid) {
|
||||||
const { content, name, type } = await callCloudApiGet(`content/${folid}/${cntid}`);
|
const signinHolder = await getCloudSigninHolder();
|
||||||
return { content, name, type };
|
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 = {};
|
const cloudConnectionCache = {};
|
||||||
@@ -278,4 +334,5 @@ module.exports = {
|
|||||||
getCloudFolderEncryptor,
|
getCloudFolderEncryptor,
|
||||||
getCloudContent,
|
getCloudContent,
|
||||||
loadCachedCloudConnection,
|
loadCachedCloudConnection,
|
||||||
|
putCloudContent,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -108,7 +108,7 @@
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import AppObjectCore from './AppObjectCore.svelte';
|
import AppObjectCore from './AppObjectCore.svelte';
|
||||||
import {
|
import {
|
||||||
cloudSigninToken,
|
cloudSigninTokenHolder,
|
||||||
currentDatabase,
|
currentDatabase,
|
||||||
DEFAULT_CONNECTION_SEARCH_SETTINGS,
|
DEFAULT_CONNECTION_SEARCH_SETTINGS,
|
||||||
expandedConnections,
|
expandedConnections,
|
||||||
@@ -334,7 +334,7 @@
|
|||||||
onClick: handleDuplicate,
|
onClick: handleDuplicate,
|
||||||
},
|
},
|
||||||
!$openedConnections.includes(data._id) &&
|
!$openedConnections.includes(data._id) &&
|
||||||
$cloudSigninToken &&
|
$cloudSigninTokenHolder &&
|
||||||
passProps?.cloudContentList?.length > 0 && {
|
passProps?.cloudContentList?.length > 0 && {
|
||||||
text: _t('connection.moveToCloudFolder', { defaultMessage: 'Move to cloud folder' }),
|
text: _t('connection.moveToCloudFolder', { defaultMessage: 'Move to cloud folder' }),
|
||||||
submenu: passProps?.cloudContentList?.map(fld => ({
|
submenu: passProps?.cloudContentList?.map(fld => ({
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
cloudSigninToken,
|
cloudSigninTokenHolder,
|
||||||
currentDatabase,
|
currentDatabase,
|
||||||
currentTheme,
|
currentTheme,
|
||||||
emptyConnectionGroupNames,
|
emptyConnectionGroupNames,
|
||||||
@@ -668,7 +668,7 @@ registerCommand({
|
|||||||
category: 'Cloud',
|
category: 'Cloud',
|
||||||
name: 'Logout',
|
name: 'Logout',
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
cloudSigninToken.set(null);
|
cloudSigninTokenHolder.set(null);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -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 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 cloudConnectionsStore = writable({});
|
||||||
|
|
||||||
// export const cloudSigninToken = getElectron()
|
|
||||||
// ? writableSettingsValue(null, 'cloudSigninToken')
|
|
||||||
// : writableWithStorage(null, 'cloudSigninToken');
|
|
||||||
|
|
||||||
export const DEFAULT_OBJECT_SEARCH_SETTINGS = {
|
export const DEFAULT_OBJECT_SEARCH_SETTINGS = {
|
||||||
pureName: true,
|
pureName: true,
|
||||||
schemaName: false,
|
schemaName: false,
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import { batchDispatchCacheTriggers, dispatchCacheChange } from './cache';
|
|||||||
import { isAdminPage, isOneOfPage } from './pageDefs';
|
import { isAdminPage, isOneOfPage } from './pageDefs';
|
||||||
import { openWebLink } from './simpleTools';
|
import { openWebLink } from './simpleTools';
|
||||||
import { serializeJsTypesReplacer } from 'dbgate-tools';
|
import { serializeJsTypesReplacer } from 'dbgate-tools';
|
||||||
import { cloudSigninToken } from '../stores';
|
import { cloudSigninTokenHolder } from '../stores';
|
||||||
|
|
||||||
export const strmid = uuidv1();
|
export const strmid = uuidv1();
|
||||||
|
|
||||||
@@ -281,8 +281,9 @@ export function installNewVolatileConnectionListener() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function installNewCloudTokenListener() {
|
export function installNewCloudTokenListener() {
|
||||||
apiOn('got-cloud-token', async ({ token }) => {
|
apiOn('got-cloud-token', async tokenHolder => {
|
||||||
cloudSigninToken.set(token);
|
console.log('HOLDER', tokenHolder);
|
||||||
|
cloudSigninTokenHolder.set(tokenHolder);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
import { apiCall } from '../utility/api';
|
import { apiCall } from '../utility/api';
|
||||||
import {
|
import {
|
||||||
cloudConnectionsStore,
|
cloudConnectionsStore,
|
||||||
cloudSigninToken,
|
cloudSigninTokenHolder,
|
||||||
currentDatabase,
|
currentDatabase,
|
||||||
expandedConnections,
|
expandedConnections,
|
||||||
openedConnections,
|
openedConnections,
|
||||||
@@ -82,7 +82,7 @@
|
|||||||
name="privateCloud"
|
name="privateCloud"
|
||||||
height="50%"
|
height="50%"
|
||||||
storageName="privateCloudItems"
|
storageName="privateCloudItems"
|
||||||
skip={!$cloudSigninToken}
|
skip={!$cloudSigninTokenHolder}
|
||||||
>
|
>
|
||||||
<WidgetsInnerContainer>
|
<WidgetsInnerContainer>
|
||||||
<SearchBoxWrapper>
|
<SearchBoxWrapper>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
visibleHamburgerMenuWidget,
|
visibleHamburgerMenuWidget,
|
||||||
lockedDatabaseMode,
|
lockedDatabaseMode,
|
||||||
getCurrentConfig,
|
getCurrentConfig,
|
||||||
cloudSigninToken,
|
cloudSigninTokenHolder,
|
||||||
} from '../stores';
|
} from '../stores';
|
||||||
import mainMenuDefinition from '../../../../app/src/mainMenuDefinition';
|
import mainMenuDefinition from '../../../../app/src/mainMenuDefinition';
|
||||||
import hasPermission from '../utility/hasPermission';
|
import hasPermission from '../utility/hasPermission';
|
||||||
@@ -149,7 +149,7 @@
|
|||||||
{#each widgets
|
{#each widgets
|
||||||
.filter(x => x && hasPermission(`widgets/${x.name}`))
|
.filter(x => x && hasPermission(`widgets/${x.name}`))
|
||||||
.filter(x => !x.isPremiumPromo || !isProApp())
|
.filter(x => !x.isPremiumPromo || !isProApp())
|
||||||
.filter(x => x.name != 'cloud-private' || $cloudSigninToken) as item}
|
.filter(x => x.name != 'cloud-private' || $cloudSigninTokenHolder) as item}
|
||||||
<div
|
<div
|
||||||
class="wrapper"
|
class="wrapper"
|
||||||
class:selected={item.name == $visibleSelectedWidget}
|
class:selected={item.name == $visibleSelectedWidget}
|
||||||
@@ -176,7 +176,7 @@
|
|||||||
<FontIcon icon={$lockedDatabaseMode ? 'icon locked-database-mode' : 'icon unlocked-database-mode'} />
|
<FontIcon icon={$lockedDatabaseMode ? 'icon locked-database-mode' : 'icon unlocked-database-mode'} />
|
||||||
</div> -->
|
</div> -->
|
||||||
|
|
||||||
{#if $cloudSigninToken}
|
{#if $cloudSigninTokenHolder}
|
||||||
<div
|
<div
|
||||||
class="wrapper"
|
class="wrapper"
|
||||||
on:click={handleCloudAccountMenu}
|
on:click={handleCloudAccountMenu}
|
||||||
|
|||||||
Reference in New Issue
Block a user