1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-03-26 21:12:59 +02:00

Cli: Fixes #2981: Add support for retrying decryption after it has failed multiple times

This commit is contained in:
Laurent Cozic 2020-04-08 18:02:31 +01:00
parent a6459d3641
commit 7ccd19e21d
7 changed files with 54 additions and 29 deletions

View File

@ -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;

View File

@ -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();
}
}

View File

@ -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}` : '';
}

View File

@ -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"

View File

@ -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';

View File

@ -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');
}

View File

@ -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();