upload error to gist

This commit is contained in:
Jan Prochazka 2024-05-24 13:12:07 +02:00
parent e04da15f72
commit 5ab0907bd8
5 changed files with 168 additions and 1 deletions

View File

@ -90,6 +90,7 @@ module.exports = ({ editMenu }) => [
{ divider: true },
{ command: 'folder.showLogs', hideDisabled: true },
{ command: 'folder.showData', hideDisabled: true },
{ command: 'new.gist', hideDisabled: true },
],
},
{

View File

@ -240,4 +240,20 @@ module.exports = {
if (opened.connection.isReadOnly) return false;
return this.loadDataCore('summaryCommand', { conid, command, row });
},
getOpenedConnectionReport() {
return this.opened.map(con => ({
status: con.status,
versionText: con.version?.versionText,
databaseCount: con.databases.length,
connection: _.pick(con.connection, [
'engine',
'useSshTunnel',
'authType',
'trustServerCertificate',
'useSsl',
'sshMode',
]),
}));
},
};

View File

@ -1,8 +1,15 @@
const crypto = require('crypto');
const path = require('path');
const { uploadsdir } = require('../utility/directories');
const { uploadsdir, getLogsFilePath } = require('../utility/directories');
const { getLogger } = require('dbgate-tools');
const logger = getLogger('uploads');
const axios = require('axios');
const os = require('os');
const fs = require('fs/promises');
const { read } = require('./queryHistory');
const platformInfo = require('../utility/platformInfo');
const _ = require('lodash');
const serverConnections = require('./serverConnections');
module.exports = {
upload_meta: {
@ -35,4 +42,80 @@ module.exports = {
get(req, res) {
res.sendFile(path.join(uploadsdir(), req.query.file));
},
uploadErrorToGist_meta: true,
async uploadErrorToGist() {
const logs = await fs.readFile(getLogsFilePath(), { encoding: 'utf-8' });
const connections = await serverConnections.getOpenedConnectionReport();
try {
const response = await axios.default.post(
'https://api.github.com/gists',
{
description: 'DbGate error report',
public: false,
files: {
'logs.jsonl': {
content: logs,
},
'os.json': {
content: JSON.stringify(
{
release: os.release(),
arch: os.arch(),
machine: os.machine(),
platform: os.platform(),
type: os.type(),
},
null,
2
),
},
'platform.json': {
content: JSON.stringify(
_.omit(
{
...platformInfo,
},
['defaultKeyfile', 'sshAuthSock']
),
null,
2
),
},
'connections.json': {
content: JSON.stringify(connections, null, 2),
},
},
},
{
headers: {
Authorization: `token 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`,
'Content-Type': 'application/json',
Accept: 'application/vnd.github.v3+json',
},
}
);
return response.data;
} catch (err) {
logger.error({ err }, 'Error uploading gist');
return {
apiErrorMessage: err.message,
};
// console.error('Error creating gist:', error.response ? error.response.data : error.message);
}
},
deleteGist_meta: true,
async deleteGist({ url }) {
const response = await axios.default.delete(url, {
headers: {
Authorization: `token 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`,
'Content-Type': 'application/json',
Accept: 'application/vnd.github.v3+json',
},
});
return true;
},
};

View File

@ -38,6 +38,7 @@ import { getSettings } from '../utility/metadataLoaders';
import { isMac } from '../utility/common';
import { doLogout, internalRedirectTo } from '../clientAuth';
import { disconnectServerConnection } from '../appobj/ConnectionAppObject.svelte';
import UploadErrorModal from '../modals/UploadErrorModal.svelte';
// function themeCommand(theme: ThemeDefinition) {
// return {
@ -865,6 +866,14 @@ registerCommand({
onClick: () => getElectron().send('window-action', 'selectAll'),
});
registerCommand({
id: 'new.gist',
category: 'New',
name: 'Upload error to gist',
onClick: () => showModal(UploadErrorModal),
});
const electron = getElectron();
if (electron) {
electron.addEventListener('run-command', (e, commandId) => runCommand(commandId));

View File

@ -0,0 +1,58 @@
<script lang="ts">
import { onMount } from 'svelte';
import FormStyledButton from '../buttons/FormStyledButton.svelte';
import FormProvider from '../forms/FormProvider.svelte';
import FormSubmit from '../forms/FormSubmit.svelte';
import FormTextField from '../forms/FormTextField.svelte';
import { apiCall } from '../utility/api';
import ModalBase from './ModalBase.svelte';
import { closeCurrentModal } from './modalTools';
import { copyTextToClipboard } from '../utility/clipboard';
import Link from '../elements/Link.svelte';
import LoadingInfo from '../elements/LoadingInfo.svelte';
import { showSnackbarSuccess } from '../utility/snackbar';
export let error = null;
let htmlUrl;
let url;
async function upload() {
const resp = await apiCall('uploads/upload-error-to-gist');
url = resp.url;
htmlUrl = resp.html_url;
}
onMount(() => {
upload();
});
async function handleDelete() {
const resp = await apiCall('uploads/delete-gist', { url });
closeCurrentModal();
showSnackbarSuccess('Gist was deleted');
}
function handleCopy() {
copyTextToClipboard(htmlUrl);
}
</script>
<ModalBase {...$$restProps}>
<svelte:fragment slot="header">Upload error</svelte:fragment>
{#if htmlUrl}
<div>
<p>Upload error to gist was successful. You could check uploaded data, if don't want to make them public, use Delete button to remove them from gist.</p>
<p><Link href={htmlUrl}>Open uploaded data</Link></p>
</div>
{:else}
<LoadingInfo message="Uploading error to gist..." />
{/if}
<svelte:fragment slot="footer">
<FormStyledButton value="Copy URL" disabled={!htmlUrl} on:click={handleCopy} />
<FormStyledButton type="button" value="Close" on:click={closeCurrentModal} />
<FormStyledButton value="Delete" disabled={!url} on:click={handleDelete} />
</svelte:fragment>
</ModalBase>