mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-22 06:26:00 +00:00
show cloud content
This commit is contained in:
@@ -4,8 +4,13 @@ const {
|
|||||||
refreshPublicFiles,
|
refreshPublicFiles,
|
||||||
callCloudApiGet,
|
callCloudApiGet,
|
||||||
callCloudApiPost,
|
callCloudApiPost,
|
||||||
|
getCloudFolderEncryptor,
|
||||||
} = require('../utility/cloudIntf');
|
} = require('../utility/cloudIntf');
|
||||||
|
const connections = require('./connections');
|
||||||
const socket = require('../utility/socket');
|
const socket = require('../utility/socket');
|
||||||
|
const { decryptConnection, recryptConnection, getInternalEncryptor } = require('../utility/crypting');
|
||||||
|
const { getConnectionLabel, getLogger, extractErrorLogData } = require('dbgate-tools');
|
||||||
|
const logger = getLogger('cloud');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
publicFiles_meta: true,
|
publicFiles_meta: true,
|
||||||
@@ -30,9 +35,14 @@ module.exports = {
|
|||||||
|
|
||||||
contentList_meta: true,
|
contentList_meta: true,
|
||||||
async contentList() {
|
async contentList() {
|
||||||
const resp = callCloudApiGet('content-list');
|
try {
|
||||||
console.log('contentList', resp);
|
const resp = await callCloudApiGet('content-list');
|
||||||
return resp;
|
return resp;
|
||||||
|
} catch (err) {
|
||||||
|
logger.error(extractErrorLogData(err), 'Error getting cloud content list');
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
getContent_meta: true,
|
getContent_meta: true,
|
||||||
@@ -79,4 +89,21 @@ module.exports = {
|
|||||||
status: 'ok',
|
status: 'ok',
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
moveConnectionCloud_meta: true,
|
||||||
|
async moveConnectionCloud({ conid, folid }) {
|
||||||
|
const conn = await connections.getCore({ conid });
|
||||||
|
const folderEncryptor = getCloudFolderEncryptor(folid);
|
||||||
|
const recryptedConn = recryptConnection(conn, getInternalEncryptor(), folderEncryptor);
|
||||||
|
await this.putContent({
|
||||||
|
folid,
|
||||||
|
cntid: conid,
|
||||||
|
content: JSON.stringify(recryptedConn),
|
||||||
|
name: getConnectionLabel(conn),
|
||||||
|
type: 'connection',
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
status: 'ok',
|
||||||
|
};
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ const connections = require('../controllers/connections');
|
|||||||
const { isProApp } = require('./checkLicense');
|
const { isProApp } = require('./checkLicense');
|
||||||
const socket = require('./socket');
|
const socket = require('./socket');
|
||||||
const config = require('../controllers/config');
|
const config = require('../controllers/config');
|
||||||
|
const simpleEncryptor = require('simple-encryptor');
|
||||||
|
|
||||||
const logger = getLogger('cloudIntf');
|
const logger = getLogger('cloudIntf');
|
||||||
|
|
||||||
@@ -239,6 +240,14 @@ async function callCloudApiPost(endpoint, body) {
|
|||||||
return resp.data;
|
return resp.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getCloudFolderEncryptor(folid) {
|
||||||
|
const { encryptionKey } = await callCloudApiGet(`folder-key/${folid}`);
|
||||||
|
if (!encryptionKey) {
|
||||||
|
throw new Error('No encryption key');
|
||||||
|
}
|
||||||
|
return simpleEncryptor.createEncryptor(encryptionKey);
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
createDbGateIdentitySession,
|
createDbGateIdentitySession,
|
||||||
startCloudTokenChecking,
|
startCloudTokenChecking,
|
||||||
@@ -248,4 +257,5 @@ module.exports = {
|
|||||||
refreshPublicFiles,
|
refreshPublicFiles,
|
||||||
callCloudApiGet,
|
callCloudApiGet,
|
||||||
callCloudApiPost,
|
callCloudApiPost,
|
||||||
|
getCloudFolderEncryptor,
|
||||||
};
|
};
|
||||||
|
|||||||
30
packages/web/src/appobj/CloudContentAppObject.svelte
Normal file
30
packages/web/src/appobj/CloudContentAppObject.svelte
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<script lang="ts" context="module">
|
||||||
|
import AppObjectCore from './AppObjectCore.svelte';
|
||||||
|
|
||||||
|
export const extractKey = data => data.cntid;
|
||||||
|
export const createMatcher =
|
||||||
|
filter =>
|
||||||
|
({ name }) =>
|
||||||
|
filterName(filter, name);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { filterName } from 'dbgate-tools';
|
||||||
|
|
||||||
|
export let data;
|
||||||
|
|
||||||
|
function createMenu() {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<AppObjectCore {...$$restProps} {data} icon={'img connection'} title={data.name} menu={createMenu}></AppObjectCore>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.info {
|
||||||
|
margin-left: 30px;
|
||||||
|
margin-right: 5px;
|
||||||
|
color: var(--theme-font-3);
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -108,6 +108,7 @@
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import AppObjectCore from './AppObjectCore.svelte';
|
import AppObjectCore from './AppObjectCore.svelte';
|
||||||
import {
|
import {
|
||||||
|
cloudSigninToken,
|
||||||
currentDatabase,
|
currentDatabase,
|
||||||
DEFAULT_CONNECTION_SEARCH_SETTINGS,
|
DEFAULT_CONNECTION_SEARCH_SETTINGS,
|
||||||
expandedConnections,
|
expandedConnections,
|
||||||
@@ -332,6 +333,17 @@
|
|||||||
text: _t('connection.duplicate', { defaultMessage: 'Duplicate' }),
|
text: _t('connection.duplicate', { defaultMessage: 'Duplicate' }),
|
||||||
onClick: handleDuplicate,
|
onClick: handleDuplicate,
|
||||||
},
|
},
|
||||||
|
!$openedConnections.includes(data._id) &&
|
||||||
|
$cloudSigninToken &&
|
||||||
|
passProps?.cloudContentList?.length > 0 && {
|
||||||
|
text: _t('connection.moveToCloudFolder', { defaultMessage: 'Move to cloud folder' }),
|
||||||
|
submenu: passProps?.cloudContentList?.map(fld => ({
|
||||||
|
text: fld.name,
|
||||||
|
onClick: () => {
|
||||||
|
apiCall('cloud/move-connection-cloud', { conid: data._id, folid: fld.folid });
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
},
|
||||||
],
|
],
|
||||||
{ divider: true },
|
{ divider: true },
|
||||||
!data.singleDatabase && [
|
!data.singleDatabase && [
|
||||||
|
|||||||
@@ -183,7 +183,6 @@ 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 cloudSigninToken = writableSettingsValue(null, 'cloudSigninToken');
|
||||||
export const cloudEncryptKeysByFolder = writableSettingsValue({}, 'cloudEncryptKeysByFolder');
|
|
||||||
|
|
||||||
// export const cloudSigninToken = getElectron()
|
// export const cloudSigninToken = getElectron()
|
||||||
// ? writableSettingsValue(null, 'cloudSigninToken')
|
// ? writableSettingsValue(null, 'cloudSigninToken')
|
||||||
|
|||||||
@@ -5,7 +5,8 @@
|
|||||||
import WidgetColumnBarItem from './WidgetColumnBarItem.svelte';
|
import WidgetColumnBarItem from './WidgetColumnBarItem.svelte';
|
||||||
|
|
||||||
import AppObjectList from '../appobj/AppObjectList.svelte';
|
import AppObjectList from '../appobj/AppObjectList.svelte';
|
||||||
import * as cloudFileAppObject from '../appobj/CloudFileAppObject.svelte';
|
import * as publicCloudFileAppObject from '../appobj/PublicCloudFileAppObject.svelte';
|
||||||
|
import * as cloudContentAppObject from '../appobj/CloudContentAppObject.svelte';
|
||||||
import { useCloudContentList, usePublicCloudFiles } from '../utility/metadataLoaders';
|
import { useCloudContentList, usePublicCloudFiles } from '../utility/metadataLoaders';
|
||||||
import { _t } from '../translations';
|
import { _t } from '../translations';
|
||||||
|
|
||||||
@@ -26,7 +27,7 @@
|
|||||||
$: cloudContentList = useCloudContentList();
|
$: cloudContentList = useCloudContentList();
|
||||||
|
|
||||||
$: emptyCloudContent = ($cloudContentList || []).filter(x => !x.items?.length).map(x => x.folid);
|
$: emptyCloudContent = ($cloudContentList || []).filter(x => !x.items?.length).map(x => x.folid);
|
||||||
$: cloudContentFlat = ($cloudContentList || []).flatMap(fld => fld.items ?? []).map(x => x.folid);
|
$: cloudContentFlat = ($cloudContentList || []).flatMap(fld => fld.items ?? []);
|
||||||
$: contentGroupTitleMap = _.fromPairs(($cloudContentList || []).map(x => [x.folid, x.name]));
|
$: contentGroupTitleMap = _.fromPairs(($cloudContentList || []).map(x => [x.folid, x.name]));
|
||||||
|
|
||||||
async function handleRefreshPublic() {
|
async function handleRefreshPublic() {
|
||||||
@@ -61,7 +62,7 @@
|
|||||||
|
|
||||||
<AppObjectList
|
<AppObjectList
|
||||||
list={cloudContentFlat || []}
|
list={cloudContentFlat || []}
|
||||||
module={cloudFileAppObject}
|
module={cloudContentAppObject}
|
||||||
emptyGroupNames={emptyCloudContent}
|
emptyGroupNames={emptyCloudContent}
|
||||||
groupFunc={data => data.folid}
|
groupFunc={data => data.folid}
|
||||||
mapGroupTitle={folid => contentGroupTitleMap[folid]}
|
mapGroupTitle={folid => contentGroupTitleMap[folid]}
|
||||||
@@ -86,7 +87,7 @@
|
|||||||
|
|
||||||
<AppObjectList
|
<AppObjectList
|
||||||
list={$publicFiles || []}
|
list={$publicFiles || []}
|
||||||
module={cloudFileAppObject}
|
module={publicCloudFileAppObject}
|
||||||
groupFunc={data => data.folder || undefined}
|
groupFunc={data => data.folder || undefined}
|
||||||
filter={publicFilter}
|
filter={publicFilter}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -351,6 +351,7 @@
|
|||||||
isExpandable={data => $openedConnections.includes(data._id) && !data.singleDatabase}
|
isExpandable={data => $openedConnections.includes(data._id) && !data.singleDatabase}
|
||||||
{filter}
|
{filter}
|
||||||
passProps={{
|
passProps={{
|
||||||
|
...passProps,
|
||||||
connectionColorFactory: $connectionColorFactory,
|
connectionColorFactory: $connectionColorFactory,
|
||||||
showPinnedInsteadOfUnpin: true,
|
showPinnedInsteadOfUnpin: true,
|
||||||
searchSettings: $connectionAppObjectSearchSettings,
|
searchSettings: $connectionAppObjectSearchSettings,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { findEngineDriver } from 'dbgate-tools';
|
import { findEngineDriver } from 'dbgate-tools';
|
||||||
import { currentDatabase, extensions, pinnedDatabases, pinnedTables } from '../stores';
|
import { currentDatabase, extensions, pinnedDatabases, pinnedTables } from '../stores';
|
||||||
import { useConfig, useConnectionInfo } from '../utility/metadataLoaders';
|
import { useCloudContentList, useConfig, useConnectionInfo } from '../utility/metadataLoaders';
|
||||||
|
|
||||||
import ConnectionList from './ConnectionList.svelte';
|
import ConnectionList from './ConnectionList.svelte';
|
||||||
import PinnedObjectsList from './PinnedObjectsList.svelte';
|
import PinnedObjectsList from './PinnedObjectsList.svelte';
|
||||||
@@ -26,6 +26,7 @@
|
|||||||
$: config = useConfig();
|
$: config = useConfig();
|
||||||
$: singleDatabase = $currentDatabase?.connection?.singleDatabase;
|
$: singleDatabase = $currentDatabase?.connection?.singleDatabase;
|
||||||
$: database = $currentDatabase?.name;
|
$: database = $currentDatabase?.name;
|
||||||
|
$: cloudContentList = useCloudContentList();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<WidgetColumnBar {hidden}>
|
<WidgetColumnBar {hidden}>
|
||||||
@@ -45,7 +46,12 @@
|
|||||||
height="35%"
|
height="35%"
|
||||||
storageName="connectionsWidget"
|
storageName="connectionsWidget"
|
||||||
>
|
>
|
||||||
<ConnectionList passProps={{ onFocusSqlObjectList: () => domSqlObjectList.focus() }} />
|
<ConnectionList
|
||||||
|
passProps={{
|
||||||
|
onFocusSqlObjectList: () => domSqlObjectList.focus(),
|
||||||
|
cloudContentList: $cloudContentList,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</WidgetColumnBarItem>
|
</WidgetColumnBarItem>
|
||||||
{/if}
|
{/if}
|
||||||
<WidgetColumnBarItem
|
<WidgetColumnBarItem
|
||||||
|
|||||||
Reference in New Issue
Block a user