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:
parent
518af9dc0a
commit
10feeeeb6b
@ -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();
|
||||
|
@ -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' ||
|
||||
|
@ -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;
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user