You've already forked joplin
							
							
				mirror of
				https://github.com/laurent22/joplin.git
				synced 2025-10-31 00:07:48 +02:00 
			
		
		
		
	Cli: Fixes #2981: Add support for retrying decryption after it has failed multiple times
This commit is contained in:
		| @@ -24,12 +24,11 @@ class Command extends BaseCommand { | ||||
| 			['-p, --password <password>', 'Use this password as master password (For security reasons, it is not recommended to use this option).'], | ||||
| 			['-v, --verbose', 'More verbose output for the `target-status` command'], | ||||
| 			['-o, --output <directory>', 'Output directory'], | ||||
| 			['--retry-failed-items', 'Applies to `decrypt` command - retries decrypting items that previously could not be decrypted.'], | ||||
| 		]; | ||||
| 	} | ||||
|  | ||||
| 	async action(args) { | ||||
| 		// change-password | ||||
|  | ||||
| 		const options = args.options; | ||||
|  | ||||
| 		const askForMasterKey = async error => { | ||||
| @@ -44,6 +43,27 @@ class Command extends BaseCommand { | ||||
| 			return true; | ||||
| 		}; | ||||
|  | ||||
| 		const startDecryption = async () => { | ||||
| 			this.stdout(_('Starting decryption... Please wait as it may take several minutes depending on how much there is to decrypt.')); | ||||
|  | ||||
| 			while (true) { | ||||
| 				try { | ||||
| 					await DecryptionWorker.instance().start(); | ||||
| 					break; | ||||
| 				} catch (error) { | ||||
| 					if (error.code === 'masterKeyNotLoaded') { | ||||
| 						const ok = await askForMasterKey(error); | ||||
| 						if (!ok) return; | ||||
| 						continue; | ||||
| 					} | ||||
|  | ||||
| 					throw error; | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			this.stdout(_('Completed decryption.')); | ||||
| 		}; | ||||
|  | ||||
| 		if (args.command === 'enable') { | ||||
| 			const password = options.password ? options.password.toString() : await this.prompt(_('Enter master password:'), { type: 'string', secure: true }); | ||||
| 			if (!password) { | ||||
| @@ -73,24 +93,8 @@ class Command extends BaseCommand { | ||||
| 				const plainText = await EncryptionService.instance().decryptString(args.path); | ||||
| 				this.stdout(plainText); | ||||
| 			} else { | ||||
| 				this.stdout(_('Starting decryption... Please wait as it may take several minutes depending on how much there is to decrypt.')); | ||||
|  | ||||
| 				while (true) { | ||||
| 					try { | ||||
| 						await DecryptionWorker.instance().start(); | ||||
| 						break; | ||||
| 					} catch (error) { | ||||
| 						if (error.code === 'masterKeyNotLoaded') { | ||||
| 							const ok = await askForMasterKey(error); | ||||
| 							if (!ok) return; | ||||
| 							continue; | ||||
| 						} | ||||
|  | ||||
| 						throw error; | ||||
| 					} | ||||
| 				} | ||||
|  | ||||
| 				this.stdout(_('Completed decryption.')); | ||||
| 				if (args.options['retry-failed-items']) await DecryptionWorker.instance().clearDisabledItems(); | ||||
| 				await startDecryption(); | ||||
| 			} | ||||
|  | ||||
| 			return; | ||||
|   | ||||
| @@ -25,19 +25,28 @@ class Command extends BaseCommand { | ||||
| 			this.stdout(`# ${section.title}`); | ||||
| 			this.stdout(''); | ||||
|  | ||||
| 			let canRetryType = ''; | ||||
|  | ||||
| 			for (const n in section.body) { | ||||
| 				if (!section.body.hasOwnProperty(n)) continue; | ||||
| 				const line = section.body[n]; | ||||
| 				this.stdout(line); | ||||
| 				const item = section.body[n]; | ||||
|  | ||||
| 				if (typeof item === 'object') { | ||||
| 					canRetryType = item.canRetryType; | ||||
| 					this.stdout(item.text); | ||||
| 				} else { | ||||
| 					this.stdout(item); | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			if (canRetryType === 'e2ee') { | ||||
| 				this.stdout(''); | ||||
| 				this.stdout(_('To retry decryption of these items. Run `e2ee decrypt --retry-failed-items`')); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		app() | ||||
| 			.gui() | ||||
| 			.showConsole(); | ||||
| 		app() | ||||
| 			.gui() | ||||
| 			.maximizeConsole(); | ||||
| 		app().gui().showConsole(); | ||||
| 		app().gui().maximizeConsole(); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -46,6 +46,8 @@ class NoteWidget extends TextWidget { | ||||
|  | ||||
| 				if (this.note_ && this.note_.encryption_applied) { | ||||
| 					this.text = _('One or more items are currently encrypted and you may need to supply a master password. To do so please type `e2ee decrypt`. If you have already supplied the password, the encrypted items are being decrypted in the background and will be available soon.'); | ||||
| 					this.text += '\n\n'; | ||||
| 					this.text += _('You may also type `status` for more information.'); | ||||
| 				} else { | ||||
| 					this.text = this.note_ ? `${this.note_.title}\n\n${this.note_.body}` : ''; | ||||
| 				} | ||||
|   | ||||
| @@ -7,7 +7,7 @@ | ||||
|     "test": "gulp buildTests -L && jasmine --config=tests/support/jasmine.json", | ||||
|     "postinstall": "npm run build && patch-package --patch-dir ../patches", | ||||
|     "build": "gulp build", | ||||
|     "start": "gulp build -L && node 'build/main.js' --profile ~/Temp/TestNotes2 --stack-trace-enabled --log-level debug --env dev" | ||||
|     "start": "gulp build -L && node 'build/main.js' --stack-trace-enabled --log-level debug --env dev" | ||||
|   }, | ||||
|   "bugs": { | ||||
|     "url": "https://github.com/laurent22/joplin/issues" | ||||
|   | ||||
| @@ -89,6 +89,10 @@ class DecryptionWorker { | ||||
| 		await this.kvStore().deleteValue(`decrypt:${typeId}:${itemId}`); | ||||
| 	} | ||||
|  | ||||
| 	async clearDisabledItems() { | ||||
| 		await this.kvStore().deleteByPrefix('decrypt:'); | ||||
| 	} | ||||
|  | ||||
| 	dispatchReport(report) { | ||||
| 		const action = Object.assign({}, report); | ||||
| 		action.type = 'DECRYPTION_WORKER_SET'; | ||||
|   | ||||
| @@ -58,6 +58,10 @@ class KvStore extends BaseService { | ||||
| 		await this.db().exec('DELETE FROM key_values WHERE `key` = ?', [key]); | ||||
| 	} | ||||
|  | ||||
| 	async deleteByPrefix(prefix) { | ||||
| 		await this.db().exec('DELETE FROM key_values WHERE `key` LIKE ?', [`${prefix}%`]); | ||||
| 	} | ||||
|  | ||||
| 	async clear() { | ||||
| 		await this.db().exec('DELETE FROM key_values'); | ||||
| 	} | ||||
|   | ||||
| @@ -150,6 +150,7 @@ class ReportService { | ||||
| 				section.body.push({ | ||||
| 					text: _('%s: %s', toTitleCase(BaseModel.modelTypeToName(row.type_)), row.id), | ||||
| 					canRetry: true, | ||||
| 					canRetryType: 'e2ee', | ||||
| 					retryHandler: async () => { | ||||
| 						await DecryptionWorker.instance().clearDisabledItem(row.type_, row.id); | ||||
| 						DecryptionWorker.instance().scheduleStart(); | ||||
| @@ -207,6 +208,7 @@ class ReportService { | ||||
| 				section.body.push({ | ||||
| 					text: _('%s (%s): %s', row.resource_title, row.resource_id, row.fetch_error), | ||||
| 					canRetry: true, | ||||
| 					canRetryType: 'resourceDownload', | ||||
| 					retryHandler: async () => { | ||||
| 						await Resource.resetErrorStatus(row.resource_id); | ||||
| 						ResourceFetcher.instance().autoAddResources(); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user