feat: better security connections credentials storage

This commit is contained in:
Fabio Di Stasio 2020-12-18 18:44:32 +01:00
parent 65ad0e954d
commit fc35f271d7
8 changed files with 56 additions and 7 deletions

5
.gitattributes vendored
View File

@ -1 +1,6 @@
* text eol=lf
*.jpg binary
*.png binary
*.gif binary
*.ico binary
*.icns binary

View File

@ -36,6 +36,7 @@ An application created with minimalism and semplicity in mind, with features in
- Query suggestions.
- Native dark theme.
- Multi language.
- Secure password storage.
- Auto updates.
## Coming soon
@ -44,7 +45,6 @@ This is a roadmap with major features will come in near future.
- Stored procedures, views, schedulers and triggers support.
- Users management (add/edit/delete).
- More secure password storage.
- Database tools (variables, process list...).
- SSL and SSH tunnel support.
- Support for other databases.

View File

@ -49,7 +49,9 @@
"dependencies": {
"@mdi/font": "^5.8.55",
"electron-log": "^4.3.0",
"electron-store": "^6.0.1",
"electron-updater": "^4.3.5",
"keytar": "^7.3.0",
"lodash": "^4.17.20",
"moment": "^2.29.1",
"monaco-editor": "^0.20.0",

View File

@ -2,7 +2,9 @@
import { app, BrowserWindow, nativeImage } from 'electron';
import * as path from 'path';
import crypto from 'crypto';
import { format as formatUrl } from 'url';
import keytar from 'keytar';
import ipcHandlers from './ipc-handlers';
const isDevelopment = process.env.NODE_ENV !== 'production';
@ -89,7 +91,14 @@ else {
});
// create main BrowserWindow when electron is ready
app.on('ready', () => {
app.on('ready', async () => {
let key = await keytar.getPassword('antares', 'user');
if (!key) {
key = crypto.randomBytes(16).toString('hex');
keytar.setPassword('antares', 'user', key);
}
mainWindow = createMainWindow();
});
}

View File

@ -1,7 +1,13 @@
import keytar from 'keytar';
import { app, ipcMain } from 'electron';
export default () => {
ipcMain.on('close-app', () => {
app.exit();
});
ipcMain.on('get-key', async event => {
const key = await keytar.getPassword('antares', 'user');
event.returnValue = key;
});
};

View File

@ -0,0 +1,8 @@
'use strict';
import { ipcRenderer } from 'electron';
export default class {
static getKey (params) {
return ipcRenderer.sendSync('get-key', params);
}
}

View File

@ -1,10 +1,20 @@
'use strict';
import Store from 'electron-store';
import Application from '../../ipc-api/Application';
const key = Application.getKey();
console.log(key);
const persistentStore = new Store({
name: 'connections',
encryptionKey: key
});
export default {
namespaced: true,
strict: true,
state: {
connections: []
connections: persistentStore.get('connections') || []
},
getters: {
getConnections: state => state.connections,
@ -20,9 +30,11 @@ export default {
mutations: {
ADD_CONNECTION (state, connection) {
state.connections.push(connection);
persistentStore.set('connections', state.connections);
},
DELETE_CONNECTION (state, connection) {
state.connections = state.connections.filter(el => el.uid !== connection.uid);
persistentStore.set('connections', state.connections);
},
EDIT_CONNECTION (state, connection) {
const editedConnections = state.connections.map(conn => {
@ -31,9 +43,11 @@ export default {
});
state.connections = editedConnections;
state.selected_conection = {};
persistentStore.set('connections', state.connections);
},
UPDATE_CONNECTIONS (state, connections) {
state.connections = connections;
persistentStore.set('connections', state.connections);
}
},
actions: {

View File

@ -1,13 +1,15 @@
'use strict';
import i18n from '@/i18n';
import Store from 'electron-store';
const persistentStore = new Store({ name: 'settings' });
export default {
namespaced: true,
strict: true,
state: {
locale: 'en-US',
explorebar_size: null,
notifications_timeout: 5
locale: persistentStore.get('locale') || 'en-US',
explorebar_size: persistentStore.get('explorebar_size') || null,
notifications_timeout: persistentStore.get('notifications_timeout') || 5
},
getters: {
getLocale: state => state.locale,
@ -18,12 +20,15 @@ export default {
SET_LOCALE (state, locale) {
state.locale = locale;
i18n.locale = locale;
persistentStore.set('locale', state.locale);
},
SET_NOTIFICATIONS_TIMEOUT (state, timeout) {
state.notifications_timeout = timeout;
persistentStore.set('notifications_timeout', state.notifications_timeout);
},
SET_EXPLOREBAR_SIZE (state, size) {
state.explorebar_size = size;
persistentStore.set('explorebar_size', state.explorebar_size);
}
},
actions: {