1
0
mirror of https://github.com/laurent22/joplin.git synced 2024-12-24 10:27:10 +02:00

Electron: Started integrating encryption

This commit is contained in:
Laurent Cozic 2017-12-14 17:58:10 +00:00
parent 55266e5694
commit 888ac8f4c2
11 changed files with 90 additions and 34 deletions

View File

@ -353,7 +353,7 @@ class Application extends BaseApplication {
this.dispatch({
type: 'TAG_UPDATE_ALL',
tags: tags,
items: tags,
});
this.store().dispatch({

View File

@ -5,6 +5,7 @@ const { FoldersScreenUtils } = require('lib/folders-screen-utils.js');
const { Setting } = require('lib/models/setting.js');
const { shim } = require('lib/shim.js');
const { BaseModel } = require('lib/base-model.js');
const MasterKey = require('lib/models/MasterKey');
const { _, setLocale } = require('lib/locale.js');
const os = require('os');
const fs = require('fs-extra');
@ -354,7 +355,14 @@ class Application extends BaseApplication {
this.dispatch({
type: 'TAG_UPDATE_ALL',
tags: tags,
items: tags,
});
const masterKeys = await MasterKey.all();
this.dispatch({
type: 'MASTERKEY_UPDATE_ALL',
items: masterKeys,
});
this.store().dispatch({

View File

@ -180,6 +180,8 @@ class SideBarComponent extends React.Component {
}
}
const itemTitle = folder.encryption_applied ? 'Encrypted 🔑' : folder.title;
return <a
className="list-item"
onDragOver={(event) => { onDragOver(event, folder) } }
@ -189,7 +191,7 @@ class SideBarComponent extends React.Component {
data-type={BaseModel.TYPE_FOLDER}
onContextMenu={(event) => this.itemContextMenu(event)}
key={folder.id}
style={style} onClick={() => {this.folderItem_click(folder)}}>{folder.title}
style={style} onClick={() => {this.folderItem_click(folder)}}>{itemTitle}
</a>
}

View File

@ -7,7 +7,7 @@ class FoldersScreenUtils {
this.dispatch({
type: 'FOLDER_UPDATE_ALL',
folders: initialFolders,
items: initialFolders,
});
}

View File

@ -272,11 +272,12 @@ class JoplinDatabase extends Database {
if (targetVersion == 9) {
queries.push('CREATE TABLE master_keys (id TEXT PRIMARY KEY, created_time INT NOT NULL, updated_time INT NOT NULL, encryption_method INT NOT NULL, checksum TEXT NOT NULL, content TEXT NOT NULL);');
queries.push('ALTER TABLE notes ADD COLUMN encryption_cipher_text TEXT NOT NULL DEFAULT ""');
queries.push('ALTER TABLE folders ADD COLUMN encryption_cipher_text TEXT NOT NULL DEFAULT ""');
queries.push('ALTER TABLE tags ADD COLUMN encryption_cipher_text TEXT NOT NULL DEFAULT ""');
queries.push('ALTER TABLE note_tags ADD COLUMN encryption_cipher_text TEXT NOT NULL DEFAULT ""');
queries.push('ALTER TABLE resources ADD COLUMN encryption_cipher_text TEXT NOT NULL DEFAULT ""');
const tableNames = ['notes', 'folders', 'tags', 'note_tags', 'resources'];
for (let i = 0; i < tableNames.length; i++) {
const n = tableNames[i];
queries.push('ALTER TABLE ' + n + ' ADD COLUMN encryption_cipher_text TEXT NOT NULL DEFAULT ""');
queries.push('ALTER TABLE ' + n + ' ADD COLUMN encryption_applied INT NOT NULL DEFAULT 0');
}
}
queries.push({ sql: 'UPDATE version SET version = ?', params: [targetVersion] });

View File

@ -263,10 +263,6 @@ class BaseItem extends BaseModel {
// List of keys that won't be encrypted - mostly foreign keys required to link items
// with each others and timestamp required for synchronisation.
const keepKeys = ['id', 'note_id', 'tag_id', 'parent_id', 'updated_time', 'type_'];
// const keepKeys = ['id', 'title', 'note_id', 'tag_id', 'parent_id', 'body', 'updated_time', 'type_'];
// if ('title' in reducedItem) reducedItem.title = '';
// if ('body' in reducedItem) reducedItem.body = '';
for (let n in reducedItem) {
if (!reducedItem.hasOwnProperty(n)) continue;
@ -278,6 +274,7 @@ class BaseItem extends BaseModel {
}
}
reducedItem.encryption_applied = 1;
reducedItem.encryption_cipher_text = cipherText;
return ItemClass.serialize(reducedItem)
@ -293,6 +290,7 @@ class BaseItem extends BaseModel {
const plainItem = await ItemClass.unserialize(plainText);
plainItem.updated_time = item.updated_time;
plainItem.encryption_cipher_text = '';
plainItem.encryption_applied = 0;
return ItemClass.save(plainItem, { autoTimestamp: false });
}

View File

@ -157,7 +157,7 @@ class Folder extends BaseItem {
return super.save(o, options).then((folder) => {
this.dispatch({
type: 'FOLDER_UPDATE_ONE',
folder: folder,
item: folder,
});
return folder;
});

View File

@ -70,7 +70,7 @@ class Tag extends BaseItem {
this.dispatch({
type: 'TAG_UPDATE_ONE',
tag: await Tag.load(tagId),
item: await Tag.load(tagId),
});
return output;
@ -84,7 +84,7 @@ class Tag extends BaseItem {
this.dispatch({
type: 'TAG_UPDATE_ONE',
tag: await Tag.load(tagId),
item: await Tag.load(tagId),
});
}
@ -132,7 +132,7 @@ class Tag extends BaseItem {
return super.save(o, options).then((tag) => {
this.dispatch({
type: 'TAG_UPDATE_ONE',
tag: tag,
item: tag,
});
return tag;
});

View File

@ -8,6 +8,7 @@ const defaultState = {
notesParentType: null,
folders: [],
tags: [],
masterKeys: [],
searches: [],
selectedNoteIds: [],
selectedFolderId: null,
@ -29,6 +30,20 @@ const defaultState = {
hasDisabledSyncItems: false,
};
function arrayHasEncryptedItems(array) {
for (let i = 0; i < array.length; i++) {
if (!!array[i].encryption_applied) return true;
}
return false
}
function stateHasEncryptedItems(state) {
if (arrayHasEncryptedItems(state.notes)) return true;
if (arrayHasEncryptedItems(state.folders)) return true;
if (arrayHasEncryptedItems(state.tags)) return true;
return false;
}
// When deleting a note, tag or folder
function handleItemDelete(state, action) {
let newState = Object.assign({}, state);
@ -72,9 +87,16 @@ function handleItemDelete(state, action) {
return newState;
}
function updateOneTagOrFolder(state, action) {
let newItems = action.type === 'TAG_UPDATE_ONE' ? state.tags.splice(0) : state.folders.splice(0);
let item = action.type === 'TAG_UPDATE_ONE' ? action.tag : action.folder;
function updateOneItem(state, action) {
// let newItems = action.type === 'TAG_UPDATE_ONE' ? state.tags.splice(0) : state.folders.splice(0);
// let item = action.type === 'TAG_UPDATE_ONE' ? action.tag : action.folder;
let itemsKey = null;
if (action.type === 'TAG_UPDATE_ONE') itemsKey = 'tags';
if (action.type === 'FOLDER_UPDATE_ONE') itemsKey = 'folders';
if (action.type === 'MASTERKEY_UPDATE_ONE') itemsKey = 'masterKeys';
let newItems = state[itemsKey].splice(0);
let item = action.item;
var found = false;
for (let i = 0; i < newItems.length; i++) {
@ -90,11 +112,13 @@ function updateOneTagOrFolder(state, action) {
let newState = Object.assign({}, state);
if (action.type === 'TAG_UPDATE_ONE') {
newState.tags = newItems;
} else {
newState.folders = newItems;
}
newState[itemsKey] = newItems;
// if (action.type === 'TAG_UPDATE_ONE') {
// newState.tags = newItems;
// } else {
// newState.folders = newItems;
// }
return newState;
}
@ -307,14 +331,14 @@ const reducer = (state = defaultState, action) => {
case 'FOLDER_UPDATE_ALL':
newState = Object.assign({}, state);
newState.folders = action.folders;
newState.folders = action.items;
break;
case 'TAG_UPDATE_ALL':
newState = Object.assign({}, state);
newState.tags = action.tags;
break;
newState.tags = action.items;
break;
case 'TAG_SELECT':
@ -328,13 +352,10 @@ const reducer = (state = defaultState, action) => {
break;
case 'TAG_UPDATE_ONE':
newState = updateOneTagOrFolder(state, action);
break;
case 'FOLDER_UPDATE_ONE':
case 'MASTERKEY_UPDATE_ONE':
newState = updateOneTagOrFolder(state, action);
newState = updateOneItem(state, action);
break;
case 'FOLDER_DELETE':
@ -342,6 +363,12 @@ const reducer = (state = defaultState, action) => {
newState = handleItemDelete(state, action);
break;
case 'MASTERKEY_UPDATE_ALL':
newState = Object.assign({}, state);
newState.masterKeys = action.items;
break;
case 'SYNC_STARTED':
newState = Object.assign({}, state);
@ -408,6 +435,11 @@ const reducer = (state = defaultState, action) => {
throw error;
}
if (action.type.indexOf('NOTE_UPDATE') === 0 || action.type.indexOf('FOLDER_UPDATE') === 0 || action.type.indexOf('TAG_UPDATE') === 0) {
newState = Object.assign({}, newState);
newState.hasEncryptedItems = stateHasEncryptedItems(newState);
}
return newState;
}

View File

@ -0,0 +1,15 @@
class DecryptionWorker {
constructor() {
this.state_ = 'idle';
}
start() {
if (this.state_ !== 'idle') return;
this.state_ = 'started';
}
}
module.exports = DecryptionWorker;

View File

@ -349,7 +349,7 @@ async function initialize(dispatch) {
dispatch({
type: 'TAG_UPDATE_ALL',
tags: tags,
items: tags,
});
let folderId = Setting.value('activeFolderId');