Skip to content
This repository has been archived by the owner on Jul 2, 2023. It is now read-only.

Commit

Permalink
Merge pull request #7 from AndresMorelos/e2ee-sync
Browse files Browse the repository at this point in the history
e2ee implementation and Export/Import option
  • Loading branch information
AndresMorelos authored Jan 2, 2022
2 parents 3875b31 + 1ae7e57 commit 476d1bb
Show file tree
Hide file tree
Showing 110 changed files with 1,507 additions and 383 deletions.
5 changes: 4 additions & 1 deletion .eslintrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,11 @@ globals:
rules:
# RULES THAT WE CONSCIOUSLY DISABLE
radix: off
func-names: off
jsx-a11y/label-has-associated-control: off

# RULES THAT WE SHOULD INVESTIGATE AND PROBABLY ENABLE
# RULES THAT WE SHOULD INVESTIGATE AND PROBABLY ENABLE]
react/jsx-props-no-spreading: off
prefer-template: off
no-underscore-dangle: off
prefer-destructuring: off
Expand Down
41 changes: 0 additions & 41 deletions .travis.yml

This file was deleted.

4 changes: 4 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"alias-resolver.type": "webpack",
"alias-resolver.accessPath": ""
}
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,9 @@ The following languages are currently being translated, if you would like to Man
* 🎨 Custom designed & highly customizable templates.
* 🏷 Custom statuses for invoices.
* 📊 Export PDF for print or email.
* 🔒Complete Privacy. You financial data stays where it belongs.
* 🔒 Complete Privacy. You financial data stays where it belongs.
* 🔒 end to end encryption. You financial data stays encripted.
* 🔄 Export or Import your financial data (all encrypted).
* 💯 Totally Free.

#### Supported Platforms
Expand Down
103 changes: 44 additions & 59 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ const { autoUpdater } = require('electron-updater');

// Place a BrowserWindow in center of primary display
const centerOnPrimaryDisplay = require('./helpers/center-on-primary-display');
const windowStateKeeper = require('./helpers/windowStateKeeper');
const { generaterRandmBytes } = require('./helpers/encryption');

// commmandline arguments
const forceDevtools = process.argv.includes('--force-devtools');
Expand Down Expand Up @@ -83,14 +85,16 @@ function createTourWindow() {
}

function createMainWindow() {
const width = 700;
const height = 600;
// Get window state
const mainWindownStateKeeper = windowStateKeeper('main');
// Creating a new window
mainWindow = new BrowserWindow({
x: mainWindownStateKeeper.x,
y: mainWindownStateKeeper.y,
width: mainWindownStateKeeper.width,
height: mainWindownStateKeeper.height,
width,
height,
minWidth: 600,
minHeight: 400,
backgroundColor: '#2e2c29',
Expand Down Expand Up @@ -173,15 +177,6 @@ function createPreviewWindow() {
});
}

function addDevToolsExtension() {
if (process.env.DEVTRON_DEV_TOOLS_PATH)
BrowserWindow.addDevToolsExtension(process.env.DEVTRON_DEV_TOOLS_PATH);
if (process.env.REACT_DEV_TOOLS_PATH)
BrowserWindow.addDevToolsExtension(process.env.REACT_DEV_TOOLS_PATH);
if (process.env.REDUX_DEV_TOOLS_PATH)
BrowserWindow.addDevToolsExtension(process.env.REDUX_DEV_TOOLS_PATH);
}

function createModalWindow(dialogOptions, returnChannel = '', ...rest) {
const width = 450;
const height = 220;
Expand Down Expand Up @@ -227,6 +222,14 @@ function createModalWindow(dialogOptions, returnChannel = '', ...rest) {
});
}

function addDevToolsExtension() {
if (process.env.DEVTRON_DEV_TOOLS_PATH)
BrowserWindow.addDevToolsExtension(process.env.DEVTRON_DEV_TOOLS_PATH);
if (process.env.REACT_DEV_TOOLS_PATH)
BrowserWindow.addDevToolsExtension(process.env.REACT_DEV_TOOLS_PATH);
if (process.env.REDUX_DEV_TOOLS_PATH)
BrowserWindow.addDevToolsExtension(process.env.REDUX_DEV_TOOLS_PATH);
}

function setInitialValues() {
// Default Logo
Expand Down Expand Up @@ -289,6 +292,12 @@ function setInitialValues() {
payment: false,
},
},
encryption: {
iv: generaterRandmBytes(),
salt: generaterRandmBytes(),
validation: null,
dataMigrated: true,
}
};

// Set initial values conditionally work for 2 level depth key only,
Expand Down Expand Up @@ -323,7 +332,8 @@ function migrateData() {
}
// Update current configs
const migratedConfigs = {
...configs, profile: info,
...configs,
profile: info,
general: {
language: appSettings.language,
sound: appSettings.sound,
Expand Down Expand Up @@ -390,6 +400,25 @@ function migrateData() {
// Remove checkUpdate and lastCheck
return { ...configs, general: omit(configs.general, ['checkUpdate', 'lastCheck']) };
},

4: configs => {
// Return current configs if this is the first time install
if (configs.encryption !== undefined) {
return configs
}

// Update current configs
return {
...configs,
encryption: {
iv: generaterRandmBytes(),
salt: generaterRandmBytes(),
validation: null,
dataMigrated: false,
}
}

}
};
// Get the current Config
const configs = appConfig.getSync();
Expand All @@ -408,7 +437,8 @@ function migrateData() {
configs
);
// Save the final config to DB
appConfig.unsetSync().setAll(migratedConfigs);
appConfig.unsetSync()
appConfig.setSync(migratedConfigs);
// Update the latest config version
appConfig.setSync('version', newMigrations[newMigrations.length - 1]);
}
Expand Down Expand Up @@ -442,51 +472,6 @@ function loadMainProcessFiles() {
files.forEach(file => require(file));
}

function windowStateKeeper(windowName) {
let window, windowState;

function setBounds() {
// Restore from appConfig
if (appConfig.hasSync(`windowState.${windowName}`)) {
windowState = appConfig.getSync(`windowState.${windowName}`);
return;
}
// Default
windowState = {
x: undefined,
y: undefined,
width: 1000,
height: 800,
};
}

function saveState() {
if (!windowState.isMaximized) {
windowState = window.getBounds();
}
windowState.isMaximized = window.isMaximized();
appConfig.setSync(`windowState.${windowName}`, windowState);
}

function track(win) {
window = win;
['resize', 'move'].forEach(event => {
win.on(event, saveState);
});
}

setBounds();

return {
x: windowState.x,
y: windowState.y,
width: windowState.width,
height: windowState.height,
isMaximized: windowState.isMaximized,
track,
};
}

function initialize() {
app.on('ready', () => {
if (!app.isDefaultProtocolClient('invoncify')) {
Expand All @@ -500,7 +485,7 @@ function initialize() {
if (isDev) addDevToolsExtension();
addEventListeners();
loadMainProcessFiles();
// Show Window
// Show Tour Window
const { showWindow } = require('./main/tour');
showWindow('startup');
});
Expand Down
81 changes: 63 additions & 18 deletions app/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,32 @@ import * as InvoicesActions from './actions/invoices';
import * as ContactsActions from './actions/contacts';

// Components
import AppNav from './components/layout/AppNav';
import AppMain from './components/layout/AppMain';
import AppNoti from './components/layout/AppNoti';
import AppUpdate from './components/layout/AppUpdate';
import { AppWrapper } from './components/shared/Layout';
import AppNav from '@components/layout/AppNav';
import AppMain from '@components/layout/AppMain';
import AppNoti from '@components/layout/AppNoti';
import AppUpdate from '@components/layout/AppUpdate';
import { AppWrapper, LoginWrapper } from '@components/shared/Layout';

//Reducers
import { getSecretKey } from './reducers/LoginReducer'
import Login from './containers/Login';

import windowStateKeeper from '../helpers/windowStateKeeper';
import resize from './helpers/resize'
import { Notify } from '../helpers/notify'

// Components
class App extends PureComponent {
constructor(props) {
super(props);
this.changeTab = this.changeTab.bind(this);
this.removeNoti = this.removeNoti.bind(this);
this.resizeWindow = this.resizeWindow.bind(this);
}

componentDidMount() {
const { dispatch } = this.props;
// Get All Data
dispatch(ContactsActions.getAllContacts());
dispatch(InvoicesActions.getInvoices());
dispatch(SettingsActions.getInitalSettings());
// Add Event Listener
ipc.on('menu-change-tab', (event, tabName) => {
Expand Down Expand Up @@ -67,6 +74,20 @@ class App extends PureComponent {
ipc.on('save-configs-to-invoice', (event, invoiceID, configs) => {
dispatch(InvoicesActions.saveInvoiceConfigs(invoiceID, configs));
});

ipc.on('file-exported', (event, options) => {
const noti = Notify(options);
// Handle click on notification
noti.onclick = () => {
ipc.send('reveal-file', options.location);
};
});

ipc.once('migrate-all-data', (event) => {
dispatch(ContactsActions.encryptContacts())
dispatch(InvoicesActions.encryptInvoices())
ipc.send('data-migrated');
})
}

componentWillUnmount() {
Expand All @@ -82,7 +103,9 @@ class App extends PureComponent {
'menu-form-toggle-note',
'menu-form-toggle-settings',
// Save template configs to invoice
'save-configs-to-invoice'
'save-configs-to-invoice',
'file-exported',
'migrate-all-data'
]);
}

Expand All @@ -96,15 +119,34 @@ class App extends PureComponent {
dispatch(UIActions.removeNoti(id));
}

resizeWindow() {
const { width, height } = windowStateKeeper('main');
ipc.send('resize-main-window', width, height);
}

render() {
const { activeTab, notifications, checkUpdatesMessage } = this.props.ui;
const { ui, secretKey } = this.props
const { activeTab, notifications, checkUpdatesMessage } = ui;
if (secretKey) {
const { dispatch } = this.props;
this.resizeWindow();
// Get Encrypted data
dispatch(InvoicesActions.getInvoices());
dispatch(ContactsActions.getAllContacts());
return (
<AppWrapper>
<AppNav activeTab={activeTab} changeTab={this.changeTab} />
<AppMain activeTab={activeTab} />
<AppNoti notifications={notifications} removeNoti={this.removeNoti} />
</AppWrapper>
);
}

return (
<AppWrapper>
<AppNav activeTab={activeTab} changeTab={this.changeTab} />
<AppMain activeTab={activeTab} />
<AppNoti notifications={notifications} removeNoti={this.removeNoti} />
</AppWrapper>
);
<LoginWrapper>
<Login />
</LoginWrapper>
)
}
}

Expand All @@ -117,6 +159,9 @@ App.propTypes = {
}).isRequired,
};

export default connect(state => ({
ui: state.ui,
}))(App);
const mapStateToProps = state => ({
secretKey: getSecretKey(state),
ui: state.ui
})

export default connect(mapStateToProps)(App);
3 changes: 3 additions & 0 deletions app/actions/contacts.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,6 @@ export const deleteContact = createAction(
ACTION_TYPES.CONTACT_DELETE,
contactID => contactID
);

// Migration from no encrypted data
export const encryptContacts = createAction(ACTION_TYPES.CONTACT_ENCRYPT)
6 changes: 6 additions & 0 deletions app/actions/exportImport.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { createAction } from 'redux-actions';
import * as ACTION_TYPES from '../constants/actions.jsx';

// Export and import Invoncify Data
export const exportData = createAction(ACTION_TYPES.EXPORT_DATA);
export const importData = createAction(ACTION_TYPES.IMPORT_DATA);
Loading

0 comments on commit 476d1bb

Please sign in to comment.