diff --git a/CliClient/app/command-e2ee.js b/CliClient/app/command-e2ee.js index 0066f8ba4..2822b6c5f 100644 --- a/CliClient/app/command-e2ee.js +++ b/CliClient/app/command-e2ee.js @@ -4,22 +4,24 @@ const { cliUtils } = require('./cli-utils.js'); const EncryptionService = require('lib/services/EncryptionService'); const DecryptionWorker = require('lib/services/DecryptionWorker'); const MasterKey = require('lib/models/MasterKey'); +const BaseItem = require('lib/models/BaseItem'); const Setting = require('lib/models/Setting.js'); class Command extends BaseCommand { usage() { - return 'e2ee '; + return 'e2ee [path]'; } description() { - return _('Manages E2EE configuration. Commands are `enable`, `disable` and `decrypt`.'); + return _('Manages E2EE configuration. Commands are `enable`, `disable`, `decrypt` and `target-status`.'); } options() { return [ // This is here mostly for testing - shouldn't be used ['-p, --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'], ]; } @@ -72,6 +74,102 @@ class Command extends BaseCommand { return; } + + if (args.command === 'target-status') { + const fs = require('fs-extra'); + const pathUtils = require('lib/path-utils.js'); + const fsDriver = new (require('lib/fs-driver-node.js').FsDriverNode)(); + + const targetPath = args.path; + if (!targetPath) throw new Error('Please specify the sync target path.'); + + const dirPaths = function(targetPath) { + let paths = []; + fs.readdirSync(targetPath).forEach((path) => { + paths.push(path); + }); + return paths; + } + + let itemCount = 0; + let resourceCount = 0; + let encryptedItemCount = 0; + let encryptedResourceCount = 0; + let otherItemCount = 0; + + let encryptedPaths = []; + let decryptedPaths = []; + + let paths = dirPaths(targetPath); + + for (let i = 0; i < paths.length; i++) { + const path = paths[i]; + const fullPath = targetPath + '/' + path; + const stat = await fs.stat(fullPath); + + // this.stdout(fullPath); + + if (path === '.resource') { + let resourcePaths = dirPaths(fullPath); + for (let j = 0; j < resourcePaths.length; j++) { + const resourcePath = resourcePaths[j]; + resourceCount++; + const fullResourcePath = fullPath + '/' + resourcePath; + const isEncrypted = await EncryptionService.instance().fileIsEncrypted(fullResourcePath); + if (isEncrypted) { + encryptedResourceCount++; + encryptedPaths.push(fullResourcePath); + } else { + decryptedPaths.push(fullResourcePath); + } + } + } else if (stat.isDirectory()) { + continue; + } else { + itemCount++; + const content = await fs.readFile(fullPath, 'utf8'); + const item = await BaseItem.unserialize(content); + const ItemClass = BaseItem.itemClass(item); + + if (!ItemClass.encryptionSupported()) { + otherItemCount++; + continue; + } + + const isEncrypted = await EncryptionService.instance().itemIsEncrypted(item); + + if (isEncrypted) { + encryptedItemCount++; + encryptedPaths.push(fullPath); + } else { + decryptedPaths.push(fullPath); + } + } + } + + this.stdout('Encrypted items: ' + encryptedItemCount + '/' + itemCount); + this.stdout('Encrypted resources: ' + encryptedResourceCount + '/' + resourceCount); + this.stdout('Other items (never encrypted): ' + otherItemCount); + + if (options.verbose) { + this.stdout(''); + this.stdout('# Encrypted paths'); + this.stdout(''); + for (let i = 0; i < encryptedPaths.length; i++) { + const path = encryptedPaths[i]; + this.stdout(path); + } + + this.stdout(''); + this.stdout('# Decrypted paths'); + this.stdout(''); + for (let i = 0; i < decryptedPaths.length; i++) { + const path = decryptedPaths[i]; + this.stdout(path); + } + } + + } } }