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

All: Fixes #2257: Prevent decryption loop when a resource cannot be decrypted

This commit is contained in:
Laurent Cozic 2020-04-08 01:00:01 +01:00
parent 518af9dc0a
commit 10feeeeb6b
5 changed files with 29 additions and 7 deletions

View File

@ -237,7 +237,6 @@ async function setupDatabaseAndSynchronizer(id = null) {
syncTarget.setFileApi(fileApi());
syncTarget.setLogger(logger);
synchronizers_[id] = await syncTarget.synchronizer();
synchronizers_[id].autoStartDecryptionWorker_ = false; // For testing we disable this since it would make the tests non-deterministic
}
encryptionServices_[id] = new EncryptionService();

View File

@ -3,6 +3,7 @@ const Tag = require('lib/models/Tag');
const Note = require('lib/models/Note');
const { reg } = require('lib/registry.js');
const ResourceFetcher = require('lib/services/ResourceFetcher');
const DecryptionWorker = require('lib/services/DecryptionWorker');
const reduxSharedMiddleware = async function(store, next, action) {
const newState = store.getState();
@ -21,6 +22,17 @@ const reduxSharedMiddleware = async function(store, next, action) {
ResourceFetcher.instance().autoAddResources();
}
// In general the DecryptionWorker is started via events, such as when an encrypted note
// is received via sync, or after an encrypted has been downloaded. However, in some cases,
// in particular when an item cannot be decrypted, the service won't retry automatically,
// since it's not useful because the data most likely is corrupted. In some
// cases the user might want to retry anyway, so we enable this by starting the service
// automatically after each full sync (which is triggered when the user presses the sync
// button, but not when a note is saved).
if (action.type === 'SYNC_COMPLETED' && action.isFullSync) {
DecryptionWorker.instance().scheduleStart();
}
if (action.type == 'NOTE_DELETE' ||
action.type == 'NOTE_UPDATE_ONE' ||
action.type == 'NOTE_UPDATE_ALL' ||

View File

@ -262,11 +262,18 @@ class Resource extends BaseItem {
await this.db().exec('INSERT INTO resources_to_download (resource_id, updated_time, created_time) SELECT ?, ?, ? WHERE NOT EXISTS (SELECT 1 FROM resources_to_download WHERE resource_id = ?)', [resourceId, t, t, resourceId]);
}
static async downloadedButEncryptedBlobCount() {
static async downloadedButEncryptedBlobCount(excludedIds = null) {
let excludedSql = '';
if (excludedIds && excludedIds.length) {
excludedSql = `AND resource_id NOT IN ("${excludedIds.join('","')}")`;
}
const r = await this.db().selectOne(`
SELECT count(*) as total
FROM resource_local_states
WHERE fetch_status = ? AND resource_id IN (SELECT id FROM resources WHERE encryption_blob_encrypted = 1)
WHERE fetch_status = ?
AND resource_id IN (SELECT id FROM resources WHERE encryption_blob_encrypted = 1)
${excludedSql}
`, [Resource.FETCH_STATUS_DONE]);
return r ? r.total : 0;

View File

@ -1,4 +1,5 @@
const BaseItem = require('lib/models/BaseItem');
const BaseModel = require('lib/BaseModel');
const MasterKey = require('lib/models/MasterKey');
const Resource = require('lib/models/Resource');
const ResourceService = require('lib/services/ResourceService');
@ -164,7 +165,7 @@ class DecryptionWorker {
try {
const decryptCounter = await this.kvStore().incValue(counterKey);
if (decryptCounter > this.maxDecryptionAttempts_) {
this.logger().debug(`DecryptionWorker: ${item.id} decryption has failed more than 2 times - skipping it`);
this.logger().debug(`DecryptionWorker: ${BaseModel.modelTypeToName(item.type_)} ${item.id}: Decryption has failed more than 2 times - skipping it`);
this.dispatch({ type: 'ENCRYPTION_HAS_DISABLED_ITEMS', value: true });
excludedIds.push(item.id);
continue;
@ -231,7 +232,7 @@ class DecryptionWorker {
this.logger().info('DecryptionWorker: completed decryption.');
const downloadedButEncryptedBlobCount = await Resource.downloadedButEncryptedBlobCount();
const downloadedButEncryptedBlobCount = await Resource.downloadedButEncryptedBlobCount(excludedIds);
this.state_ = 'idle';

View File

@ -28,7 +28,6 @@ class Synchronizer {
this.logger_ = new Logger();
this.appType_ = appType;
this.cancelling_ = false;
this.autoStartDecryptionWorker_ = true;
this.maxResourceSize_ = null;
this.downloadQueue_ = null;
this.clientId_ = Setting.value('clientId');
@ -266,6 +265,10 @@ class Synchronizer {
}
}
isFullSync(steps) {
return steps.includes('update_remote') && steps.includes('delete_remote') && steps.includes('delta');
}
// Synchronisation is done in three major steps:
//
// 1. UPLOAD: Send to the sync target the items that have changed since the last sync.
@ -842,7 +845,7 @@ class Synchronizer {
this.onProgress_ = function() {};
this.progressReport_ = {};
this.dispatch({ type: 'SYNC_COMPLETED' });
this.dispatch({ type: 'SYNC_COMPLETED', isFullSync: this.isFullSync(syncSteps) });
this.state_ = 'idle';